Error format
Every error is JSON:
{ "error": "invalid_document", "message": "Document failed validation",
"issues": [{ "code": "required_hidden", "node": "restore", "message": "…" }] }
| Status | error |
Meaning |
|---|---|---|
| 400 | invalid_* |
malformed request: invalid_json, invalid_body, invalid_screen, … |
| 401 | unauthorized |
missing or invalid key or token |
| 402 | plan_limit |
a plan limit was reached; users already counted keep working and reads never stop |
| 403 | app_disabled |
the app is switched off; also consent_required, ai_disabled on AI routes and anonymous_disabled on /tokens/anonymous |
| 404 | not_found |
unknown route or record |
| 409 | conflict |
the server version differs from baseVersion; current holds the server copy |
| 413 | payload_too_large |
the body is over the size limit |
| 422 | invalid_document |
the document failed validation; issues lists each one |
| 429 | rate_limited |
too many requests; wait for the Retry-After header (seconds) |
| 503 | unavailable |
try again later; provider_unavailable on AI routes |
Validation issues carry code, and where it applies node and field. The codes are the same in
every SDK and on the server, for example required_hidden, required_missing, fixed_changed,
component_not_portable, bundle_split, option_locked, style_locked, theme_contrast,
nav_start_not_allowed, too_many_parts, too_many_screens and limit_exceeded.
The SDKs keep working through every error: a write that fails stays on the device, and screens render the user's cached layout or your default.
Limits
| Limit | Value |
|---|---|
| Layout document size | 64 KB |
| Nodes per document | 500 |
| User screens | 6 per user, 20 parts each |
| Named designs | 10 per user |
| Versions | 40 per user |
| Undo | 50 steps |
| Node ids | 128 characters |
| Labels | 200 characters |
| Token lifetime | 3600 seconds |
Screen, part, design, version and undo limits are set by your catalog's policies; the values above are the ones the Memory Tin limits run used.