Error codes
Stable codes returned by the API and MCP, grouped by area, with the status code each one maps to.
Every failure uses the envelope described in Conventions. Branch on code, never on message.
Auth and access
| Code | Status | Meaning |
|---|
unauthorized | 401 | Missing or expired token. |
invalid_credentials | 401 | Wrong email or password. |
forbidden | 403 | Authenticated, but the grant denies this action. |
passkey_invalid | 401 | The passkey assertion did not verify. |
passkey_registration_failed | 400 | The passkey could not be registered. |
Validation
| Code | Status | Meaning |
|---|
invalid_input | 400 | Body or query failed validation; check details.path. |
conflict | 409 | The write collides with existing state. |
not_found | 404 | Generic missing resource. |
Websites and pages
| Code | Status | Meaning |
|---|
website.not_found | 404 | No such website, or no access. |
website.web_integrations.preview_unavailable | 403 | Web integrations are not available in preview. |
page.not_found | 404 | No such page. |
page.component.not_found | 404 | No such page component. |
template.not_found | 404 | No such template. |
subscription.plan_limit.unavailable | 402 | The plan does not allow this action. |
Objects
| Code | Status | Meaning |
|---|
object.type.not_found | 404 | No such object type. |
object.entry.not_found | 404 | No such entry. |
object.entry.not_found_generic | 404 | No such entry, or no permission to see it. |
object.entry.single_exists | 409 | A single-kind type already has its entry. |
object.entry.locked | 409 | The entry cannot be changed in its current state. |
object.field.invalid | 400 | A field value failed its constraints. |
object.field.required | 400 | A required field is missing. |
object.field.string | 400 | Text length or pattern failed. |
object.field.relation | 400 | The related entry does not exist or is not allowed. |
object.field.max_items | 400 | Too many items in a multi-value field. |
object.field.file_size | 400 | The uploaded file exceeds the field limit. |
object.field.datetime_not_configured | 400 | The date field has no configuration. |
object.field.datetime_invalid | 400 | The date value is not a valid date. |
object.user.email_exists | 409 | An account with that email already exists. |
object.lifecycle.unknown_field | 400 | The lifecycle config references a missing field. |
object.lifecycle.unsupported_field_type | 400 | The lifecycle action cannot use that field type. |
Design
| Code | Status | Meaning |
|---|
design.block_not_found | 404 | The block id is not in the document. |
design.op_bad_path | 400 | An ops path does not exist on the block. |
design.op_invalid | 400 | The op is malformed or not allowed. |
design.ops_or_content | 400 | Send ops or content, not both. |
design.json_parse | 400 | A string looked like JSON but did not parse. |
Files, docs, and runtime
| Code | Status | Meaning |
|---|
file.directory.not_found | 404 | No such directory. |
file.managed | 403 | The file is managed by the platform and cannot be changed. |
docs.not_found | 404 | No such docs path. |
docs.bad_request | 400 | A docs bundle call had no paths. |
report.not_found | 404 | No such moderation report. |
form.spam_rejected | 400 | The submission was rejected as spam. |
agent.session.not_found | 404 | No such agent session. |
unexpected | 500 | Unhandled failure. Retry, then report it. |