error_code never changes wording, you can build dashboards and alerts on it with confidence.
The codes
| Status | error_code | Cause | Whose problem |
|---|---|---|---|
| 401 | MISSING_TOKEN | No Authorization: Bearer header | Agent |
| 401 | INVALID_TOKEN | Malformed JWT or bad signature | Agent |
| 401 | EXPIRED_TOKEN | exp is in the past | Agent (SDK should refresh) |
| 401 | TOKEN_NOT_YET_VALID | nbf is in the future | Clock skew |
| 401 | WRONG_AUDIENCE | aud doesn’t match your platform_id | Your config |
| 401 | WRONG_ISSUER | iss isn’t an accepted MudraID issuer (default mudraid-identity; configurable) | Config, or an attack |
| 403 | MISSING_SCOPE | Token valid, but lacks the route’s scope | Agent not granted it |
| 404 | ROUTE_NOT_FOUND | No rule for the route, or skip: true | By design |
| 500 | JWKS_UNAVAILABLE | Couldn’t fetch MudraID’s keys to verify | Operator / network |
| 500 | MIDDLEWARE_NOT_READY | YAML couldn’t be loaded or parsed | Operator |
How to read them at a glance
Group them by who needs to act:- 401s — the token is the problem. Usually the agent isn’t sending one, or it expired. With the SDK in use, expiry should be auto-refreshed, so a steady stream of
EXPIRED_TOKENis worth investigating (clock skew, a non-SDK caller). - 403
MISSING_SCOPE— authentic but not authorized. The agent is who it says it is; it just wasn’t granted that scope. This is an access decision, not a bug — don’t “fix” it by widening scopes reflexively. WRONG_AUDIENCE— almost always your config. Theplatform_idin your YAML doesn’t match what MudraID issued tokens for. Re-export the file and redeploy.- 500s — your side, not the agent’s.
JWKS_UNAVAILABLEis a connectivity problem reaching MudraID;MIDDLEWARE_NOT_READYis a broken YAML. Neither means the agent did anything wrong.
What to alert on
- A spike in
JWKS_UNAVAILABLE→ connectivity to MudraID is degraded. - Any
MIDDLEWARE_NOT_READY→ you shipped a bad scopes file; page yourself. - A spike in
MISSING_SCOPEfrom one agent → it’s trying to do something it wasn’t granted; could be a misconfigured integration or a probe.

