Where Amazon Bedrock AgentCore errors come from
An error from InvokeAgentRuntime comes either from AgentCore itself or from your container, and the exception name says which:
- AgentCore rejected the request -
ValidationException,AccessDeniedException,ResourceNotFoundException,ThrottlingException,ServiceQuotaExceededExceptionand the 409RetryableConflictException. The request never reached your code. - Your container failed -
RuntimeClientError, withReceived error (STATUS) from runtime: 422 means your code rejected the payload, 500 that it raised an exception, 403 often that the container did not start, and 424 that it could not be started. The details are in the runtime's CloudWatch log group,/aws/bedrock-agentcore/runtimes/AGENT_ID-ENDPOINT(the endpoint isDEFAULTunless you call another qualifier).
An AgentCore Gateway hides its targets' errors behind An internal error occurred. Please retry later. until you set its exceptionLevel to DEBUG; then the real message comes back in the tool result's text and in _meta.debug. The AgentCore Gateway Target Configurator shows the outbound auth and service role permissions each target type needs.
SigV4 or a bearer token: inbound auth
A runtime accepts either IAM (SigV4) requests or JWT bearer tokens, not both - calling it the other way gives Authorization method mismatch. With a JWT authorizer you cannot use the AWS SDK or CLI, which always sign with SigV4: send an HTTPS request to https://bedrock-agentcore.REGION.amazonaws.com/runtimes/URL_ENCODED_ARN/invocations?qualifier=DEFAULT with Authorization: Bearer TOKEN and a session ID of at least 33 characters in X-Amzn-Bedrock-AgentCore-Runtime-Session-Id.
| Authorizer field | Token claim it checks | What to check |
|---|---|---|
| discoveryUrl | iss must be the issuer the URL describes | A URL of another user pool or Region; it must end with /.well-known/openid-configuration |
| allowedClients | client_id must be in the list | A Cognito ID token, which has no client_id |
| allowedAudience | one of the aud values must be in the list | A Cognito access token, which has aud only with a resource binding |
| allowedScopes | at least one scope must be in the list | A token from a sign-in API call, which carries only aws.cognito.signin.user.admin |
| customClaims | the named claims must match | The value type: STRING takes EQUALS, STRING_ARRAY takes CONTAINS or CONTAINS_ANY |
Every field you set is checked. The same authorizer configuration protects an AgentCore Gateway. With IAM instead, a call with the X-Amzn-Bedrock-AgentCore-Runtime-User-Id header needs bedrock-agentcore:InvokeAgentRuntimeForUser besides bedrock-agentcore:InvokeAgentRuntime. The AgentCore Token Flow Planner shows which field to set for your identity provider and how each kind of client gets its token.
Ports and paths per protocol
Many runtime errors - a 504, a RuntimeClientError without logs - come from a container that does not listen where AgentCore sends the request. The server must listen on 0.0.0.0, on an ARM64 image:
| Protocol | Port | Path |
|---|---|---|
| HTTP | 8080 | /invocations, /ws for WebSocket, /ping for health |
| MCP | 8000 | /mcp |
| A2A | 9000 | /, agent card at /.well-known/agent-card.json |
| AG-UI | 8080 | /invocations (SSE), /ws |
The AgentCore Dockerfile Checker checks a Dockerfile against these, and against the non-numeric USER that breaks images of more than 53 layers.
Frequently asked questions
Is the error or the token sent anywhere?
No. Both are read in your browser: nothing you paste is uploaded, processed on a server or stored. The page only counts that the decoder was used, with which error and whether a token was pasted, never the text. The token is decoded, not verified - its signature would need your provider's keys - and it stays usable until it expires, so paste only into pages you trust.
Why does my long-running agent stop after 15 minutes?
A synchronous request may last 15 minutes, and a session idle for 15 minutes (by default) is ended. For longer work, stream the response (up to 60 minutes) or run it in the background and answer HealthyBusy on /ping until it is done (up to 8 hours). Set time_of_last_update in the ping response only when the status changes - setting it on every ping keeps idle sessions alive until their maximum lifetime and uses up the session quota. The AgentCore Limits Checker shows every limit a described agent will hit.
I updated my agent - why do I still get the old behavior?
A session keeps the code it was created with until it ends, even after UpdateAgentRuntime. Use a new session ID to get the new version.
How is this different from the IAM Access Denied Decoder?
The IAM Access Denied Decoder reads any service's access denied message and tells which policy type denied it. This decoder knows AgentCore's own errors: the container, the runtime's inbound auth, the gateway and outbound OAuth.
References
Troubleshoot AgentCore Runtime
Authenticate and authorize with Inbound Auth and Outbound Auth
Configure inbound JWT authorizer
Understand the AgentCore Runtime service contract
IAM Permissions for AgentCore Runtime
Turn on gateway debugging messages
OAuth 2.0 authorization URL session binding
Quotas for Amazon Bedrock AgentCore