Errors
REST and MCP share one error taxonomy and one status mapping — they cannot silently diverge on what a given error means.
Error shape
{
"ok": false,
"error": { "code": "NOT_FOUND", "message": "...", "details": { ... } }
} Codes
| Code | HTTP status |
|---|---|
NOT_FOUND | 404 |
INVALID_ARGUMENT | 400 |
UNAUTHORIZED | 401 |
FORBIDDEN | 403 |
CONFLICT | 409 |
UNSUPPORTED | 422 |
INVARIANT_VIOLATION | 500 |
TEMPORARY_UNAVAILABLE | 503 |
RATE_LIMITED | 429 |
ENTITY_NOT_FOUND | 404 |
FACT_TOPIC_NOT_FOUND | 404 |
REALITY_NOT_RESOLVED | 404 |
Public discovery errors vs. resource privacy
ENTITY_NOT_FOUND, FACT_TOPIC_NOT_FOUND, and REALITY_NOT_RESOLVED
are diagnostic on purpose — they tell you exactly which part of your request didn't resolve, or
that it resolved but nothing has been observed yet. This is deliberately different from a
Reality Lock you don't own, which always returns the same
generic NOT_FOUND whether it doesn't exist or simply isn't yours — never enough
detail to enumerate other principals' resources.
What you'll never see
An internal invariant violation is always returned as a generic
INVARIANT_VIOLATION — its real underlying message is written only to AIality's own
server-side structured log, never to the client.