Troubleshooting
This page collates common errors from across the TramAI guides into a single reference.
0.6.0 Failure Signatures
Five failures are new or newly explicit in 0.6.0. If a deployment that used to start now refuses to, or an error type changed, start here.
Sovereign profile: tramai.sovereign.enabled=false is rejected
Symptom: the application fails to start with
tramai.sovereign.enabled=false is not supported: tramai.profile is the sole runtime selector.
Remove tramai.sovereign.enabled or set it to true; to run the standard runtime select
tramai.profile=standard (or omit it).
Cause: the property is a leftover compatibility switch from the 0.4.x/0.5.x separate starter. tramai.profile is the only selector in 0.6.0, so the flag has no meaning.
Fix: delete tramai.sovereign.enabled from your configuration. To run the standard runtime, set tramai.profile: standard (or remove the property entirely).
Sovereign profile: allowlist, zone, or route validation fails at startup
Symptom: startup fails with tramai-sovereign-spring-* codes — for example tramai-sovereign-spring-missing-allowed-models, tramai-sovereign-spring-provider-zone-missing, tramai-sovereign-spring-model-route-unknown-provider, or tramai-sovereign-spring-invalid-provider-zone.
Cause: the tramai.sovereign.* block is incomplete. The rules are: non-empty allowed-models and allowed-providers; every allowed provider needs a provider-zones entry using a real ProviderTrustZone value; every allowed model needs a models route; every route target must be an allowed provider.
Fix: complete the allowlist block. The full rule table, including the embedded-path codes (offline-profile-non-local-provider-rejected, artifact-digest-required-for-local-model, artifact-verification-not-configured), is in the Sovereign Runtime Quickstart. A profile value outside standard / sovereign fails with Unsupported tramai.profile '<value>'. Supported values: standard, sovereign.
Stores: IllegalStateException where SQLException used to be
Symptom: a catch block for java.sql.SQLException no longer fires; the caller sees IllegalStateException with a generic message.
Cause: this is intended. JDBC stores map driver and SQL failures to IllegalStateException with redacted details, and never leak SQL text, table names, connection strings, or vendor diagnostics.
Fix: catch IllegalStateException (or RuntimeException). Do not attempt to recover the raw SQLException — it is deliberately gone. Coroutine CancellationException and TramAI domain exceptions still pass through unwrapped, so keep distinguishing those from storage failures.
Cancellation is never wrapped
Symptom: a cancelled request is retried, counted as a provider failure, triggers a fallback, or surfaces as some other exception type.
Cause: application code swallowed it. TramAI itself preserves and propagates CancellationException on every path.
Fix: in every catch (e: Exception) block around TramAI calls, call e.rethrowIfCancellation() (from dev.tramai.core.coroutines) before handling the error. Never log-and-continue on cancellation, and never translate it into a domain error.
Image retrieval is rejected as unsafe
Symptom: IllegalArgumentException from multimodal image retrieval — unsupported outbound scheme, outbound URI must not contain user info, outbound host is restricted, outbound host resolves to a restricted address, failed to resolve outbound host, or Image download exceeds maximum size.
Cause: the SSRF admission boundary. Non-HTTP(S) schemes, embedded credentials, localhost, and loopback/link-local/private/CGNAT/ULA addresses are refused before any connection is made, redirect targets are re-validated, and the payload is capped.
Fix: fetch images from public HTTP(S) endpoints. If you genuinely need a private destination (an internal asset store, for example), do not weaken the check in application code — download through your own allowlisted path and hand TramAI the bytes as an ImagePart. See Production Hardening & Security.
Model Not Found
Symptom: ModelNotFoundException: Model 'xxx' is not mapped to any provider.
Cause: An operation references a model name that has not been mapped to a provider in your TramAI engine configuration.
Solution: Ensure every model is explicitly mapped:
val tramai = Tramai {
provider(OpenAiProvider(...), name = "openai")
model("gpt-4o", "openai") // required mapping
}
Structured Output Parsing Fails
Symptom: StructuredOutputException: Failed to parse AI response into type 'YourType'. Logs show invalid JSON or wrong schema.
Cause: The model failed to follow the requested output format. Common with smaller models.
Solutions:
- Use a more capable model (
gpt-4o,claude-sonnet-4-20250514) - Add explicit format instructions in your
@Operation(prompt = "...") - Check that retries are enabled — TramAI feeds validation errors back to the model on retry
- Default retries: 2. Configurable via
@Operation(maxRetries = N)
Provider Authentication Failures
Symptom: ProviderException: Unauthorized (401), AuthenticationException, or similar auth error.
Causes: Missing, invalid, expired, or rotated API key. Environment variable not picked up.
Solutions:
- Verify the environment variable:
echo $OPENAI_API_KEY - In Spring Boot, check
application.yaml:tramai: providers: openai: api-key: ${OPENAI_API_KEY} - Use
SecretValueResolverfor secure credential management - Check that the API key has not been rotated or revoked at the provider console
- For Azure OpenAI, verify the endpoint URL and API version are correct
Provider Timeout Errors
Symptom: ProviderException: Request timed out, java.net.SocketTimeoutException, or Read timed out.
Causes: Network latency, provider overload, or tight client timeouts.
Solutions:
- Increase the HTTP client timeout in your provider configuration
- Check network connectivity between your application and the provider endpoint
- Verify proxy/firewall settings if using a corporate network
- For Ollama, ensure the service is running and accessible:
curl http://localhost:11434/api/tags - Consider circuit breaker and retry configuration to handle transient timeouts
Provider Rate Limit Errors
Symptom: ProviderException: 429 Too Many Requests, RateLimitError, or Retry-After headers in logs.
Causes: Exceeding the provider's API rate limit or token-per-minute quota.
Solutions:
- Enable TramAI retry policy with exponential backoff (built into the engine):
retryPolicy( RetryPolicySettings( maxRetryAfterMillis = 20_000, jitterRatio = 0.1, ), ) - Reduce concurrent operation throughput
- Increase your provider plan tier if rate limits are consistently hit
- Implement a token-bucket rate limiter on your side for predictable usage
Spring Bean Injection Fails
Symptom: NoSuchBeanDefinitionException: No qualifying bean of type 'YourAiService' available.
Causes and solutions:
- Ensure
@AiServiceis on the interface, not an implementation class - Check that the interface is in a package scanned by Spring (under
@SpringBootApplicationor explicit@ComponentScan) - Verify a TramAI Spring runtime is on the classpath:
tramai-spring-boot-starter(Spring Boot auto-configuration) ortramai-spring(plain Spring context) - Verify at least one provider is available — a
tramai-spring-provider-*adapter with its properties, or aModelProviderbean. Under the sovereign profile, resolving zero providers fails startup withtramai.profile=sovereign requires at least one model provider
ClassNotFound / NoClassDefFoundError
Symptom: java.lang.NoClassDefFoundError: dev/tramai/core/... at runtime.
Cause: Missing optional module dependency.
Solution: Ensure all required modules are in your build file:
dependencies {
implementation(platform("dev.tramai:tramai-bom:0.6.0"))
implementation("dev.tramai:tramai-standalone")
implementation("dev.tramai:tramai-openai")
}
TramAI modules are opt-in. You need:
tramai-standalone(non-Spring runtime) ortramai-spring-boot-starter(Spring Boot) as the runtime entry point — adding the BOM first means no individual version pins- at least one provider module (
tramai-openai,tramai-anthropic,tramai-ollama, or atramai-spring-provider-*adapter for Spring) tramai-structuredis pulled transitively by standalone/spring- optional published modules:
tramai-observability,tramai-orchestration,tramai-scheduler,tramai-platform,tramai-sovereign,tramai-security
tramai-server, tramai-dashboard, and tramai-mcp are internal to the TramAI repository — they are not published artifacts, so a NoClassDefFoundError naming them means the code path belongs to a different deployment shape.
Native Image Build Fails
Symptom: com.oracle.svm.core.jdk.proxy.DynamicProxyProxyCreationError or missing proxy at runtime.
Cause: @AiService interface not registered in GraalVM proxy-config.json.
Solution: Generate and include proxy metadata:
NativeImageProxyConfig.write(
outputPath = Path.of("src/main/resources/META-INF/native-image/.../proxy-config.json"),
InvoiceAnalyzer::class,
)
See Native Image for the full workflow.
Native Image: Reflection Errors
Symptom: java.lang.ClassNotFoundException or reflective access errors in native image.
Cause: TramAI or provider libraries need reflection hints not included in the image.
Common fixes:
- Add
--enable-url-protocols=httpsif using HTTPS providers - Add Jackson reflection hints for your data classes
- Add
-H:ReflectionConfigurationFiles=...for provider-specific reflection - Test with
-H:+ReportUnsupportedElementsAtRuntimefor diagnostics
Spring Boot Configuration Issues
Symptom: TramAI beans are not configured as expected, or auto-configuration fails silently.
Common causes:
| Symptom | Likely cause | Fix |
|---|---|---|
| Wrong model used | Property typo in application.yaml | Check tramai.models.* keys |
| Default provider not set | Missing tramai.default-provider | Add tramai.default-provider: openai |
| Provider not found | Missing provider section, missing adapter dependency, or no API key | Check tramai.providers.* and the tramai-spring-provider-* dependency |
| DLP not working | Multiple DlpInterceptor beans | Define exactly one |
| Observability missing | OTel not on classpath | Add tramai-observability dep |
| Startup rejects the profile | Unsupported tramai.profile value | Use standard or sovereign |
| Sovereign profile fails validation | Incomplete tramai.sovereign.* allowlist block | See the 0.6.0 failure signatures |
Provider-Specific Errors
| Provider | Common Error | Cause | Fix |
|---|---|---|---|
| OpenAI | 429 Too Many Requests | Rate limit exceeded | Increase retry budget or reduce concurrency |
| Anthropic | 529 Overloaded | Anthropic server overload | Retry with backoff — built into engine |
| Ollama | Connection refused | Ollama not running locally | Start ollama serve or check base URL |
| Azure OpenAI | 401 Unauthorized | Wrong endpoint or API version | Verify endpoint URL and API version |
| Bedrock | AccessDeniedException | Missing AWS IAM permissions | Check role policy for Bedrock access |
Builder Configuration Mistakes
Common mistakes when using the Tramai { ... } builder DSL.
| Symptom | Cause | Fix |
|---|---|---|
IllegalArgumentException: Provider 'xxx' not found | Model references a provider name that was never registered | Check provider(...) call — the name parameter must match the model mapping |
IllegalStateException: No default provider | No provider was marked default = true but the model has no explicit provider route | Add default = true to one provider or always qualify model names |
MissingMethodException: No signature of method | DSL block references a method not available in the current module | Check that the required dependency (e.g. tramai-orchestration) is on the classpath |
| Model silently falls back | fallbackModel was configured but the fallback provider is missing or misconfigured | Verify both primary and fallback providers are registered and healthy |
NullPointerException in builder | Required property not set (e.g. API key is null) | Ensure all required properties are provided before passing to the builder |
Orchestration Errors
Symptom: Resuming a suspended workflow throws PolicyViolationException with reason Workflow resume is not enabled and reason code workflow-resume-disabled.
Cause: PolicyConfiguration.allowWorkflowResume defaults to false. The engine evaluates every resume at the mandatory BEFORE_WORKFLOW_RESUME enforcement point, and the secure policy denies it unless the deployment opts in (DefaultPolicyEngine returns PolicyDecision.Deny("Workflow resume is not enabled", "workflow-resume-disabled")).
Fix: Opt in explicitly on the policy configuration your runtime uses:
val configuration = PolicyConfiguration.secure()
.copy(allowWorkflowResume = true)
The sovereign profile sets this for you, but a hand-built DefaultPolicyEngine does not. Enabling resume does not relax the other enforcement points — tool exposure, execution, and result reinjection are still evaluated independently.
Scheduler Errors
| Symptom | Cause | Fix |
|---|---|---|
| Cron expression invalid | Wrong field count or values | Use 5 or 6 fields; check minutes (0-59), hours (0-23) |
| Schedule never fires | Business-hours filter active | Check businessHoursOnly config |
| Misfired ticks | Worker was down | Check misfireThreshold; increase if needed |
| Delay step never resumes | Scheduler polling not configured | Ensure ScheduledWorkflowTimer is running |
Server Errors
| Symptom | Cause | Fix |
|---|---|---|
| 400 Bad Request | Invalid workflow JSON | Check initial state matches workflow state type |
| 401 Unauthorized | Invalid webhook signature | Verify tramai.server.webhooks.secret |
| 413 Request Too Large | Body exceeds limit | Increase max-request-body-bytes |
| 404 Not Found | Unknown workflow or run name | Check workflow registration and run ID |
| SSE stream ends early | Run reached terminal state | This is expected — check status for result/error |
Platform Errors
| Symptom | Cause | Fix |
|---|---|---|
| 401 on platform endpoints | Missing or invalid API key | Provide X-API-Key header |
| 403 Forbidden | Key lacks required scope | Check key scopes include run/read/admin |
| 429 Too Many Requests | Rate limit exceeded | Check Retry-After header; increase key capacity |
| Plugin not found | JAR not in plugin directory | Drop JAR in tramai.platform.plugins.dir and enable via API |
| Team/project not found | Tenant bootstrap pending | Create team/project via repository or seed data |
Logging Diagnostics
Enable DEBUG logging for TramAI internals to trace execution:
logging:
level:
dev.tramai: DEBUG
This reveals:
- provider resolution decisions
- retry attempt pacing
- structured output parsing details
- circuit breaker state transitions
- interceptor execution order
Still Having Trouble?
- Enable DEBUG logging for
dev.tramaito see detailed execution traces - Check the GitHub Issues for known problems
- Review the relevant guide page for your use case:
