# Error codes > Stable machine-readable error codes and the RFC 9457 problem-details format — generated from the API source. Errors are [RFC 9457 problem details](https://www.rfc-editor.org/rfc/rfc9457) with content type `application/problem+json`. Every error carries a stable machine-readable `code`, a `requestId` for support, and — for validation failures — a `fields` array of `{ path, message }` items. ```json { "type": "https://myna.sh/errors/validation-failed", "title": "Validation failed", "status": 422, "code": "VALIDATION_FAILED", "detail": "One or more fields are invalid.", "requestId": "req_6f2c…", "fields": [ { "path": "title", "message": "Required" } ] } ``` `type` dereferences: every URI under `https://myna.sh/errors/` is a page describing that problem type and what to do about it. Branch on `code` rather than on the status, which several codes share. ## Codes | Code | HTTP status | Title | Meaning | |---|---|---|---| | `VALIDATION_FAILED` | 422 | Validation failed | The request body or the entry data failed validation against its collection schema. The fields array names every offending path and what is wrong with it. [What to do →](https://myna.sh/errors/validation-failed) | | `AUTHENTICATION_REQUIRED` | 401 | Authentication required | No credential was presented, or the one presented is not recognized — expired, revoked, or never valid. [What to do →](https://myna.sh/errors/authentication-required) | | `REAUTHENTICATION_REQUIRED` | 403 | Re-authentication required | The session is valid but not recent enough. Approving a CLI device code or an MCP connector mints a credential that outlives the session approving it, so both require a re-authentication no older than five minutes. [What to do →](https://myna.sh/errors/reauthentication-required) | | `IDENTITY_REQUIRED` | 401 | Signed identity required | The board only accepts submissions from an identified reporter, and the request did not carry a signed identity — either none was sent, or its signature did not verify against the ingest key's identity secret. An unsigned claim about who somebody is is ignored rather than trusted, so it counts as none. [What to do →](https://myna.sh/errors/identity-required) | | `PERMISSION_DENIED` | 403 | Permission denied | The credential is valid but does not carry the capability this route requires, or it is an API key confined to a different set of collections. [What to do →](https://myna.sh/errors/permission-denied) | | `NOT_FOUND` | 404 | Resource not found | No such resource within the caller's tenancy. It is also the answer where confirming that something exists would itself leak: an expired invitation token and one that never existed are indistinguishable on purpose. [What to do →](https://myna.sh/errors/not-found) | | `PRODUCT_NOT_ENABLED` | 404 | Product not enabled | The route belongs to a Myna product this project does not run. Myna is a platform of separate products — Content and Feedback — and a project enables each one deliberately, so a route from a product that is off has no resource behind it. [What to do →](https://myna.sh/errors/product-not-enabled) | | `CONFLICT` | 409 | Conflict | The request contradicts current state: a slug already in use, an asset still referenced by a live revision, a change set already closed or published. [What to do →](https://myna.sh/errors/conflict) | | `STALE_REVISION` | 409 | Stale revision | The entry moved after this change was staged or read. The details object carries the revision you expected and the one that is current. Publish refuses a stale base rather than merging it, because merging would change what a reviewer approved. [What to do →](https://myna.sh/errors/stale-revision) | | `PLAN_LIMIT_REACHED` | 402 | Plan limit reached | A hard entitlement is exhausted: projects, members, webhook endpoints, storage, or maximum upload size. Soft limits never produce this, and published content and assets stay online through an overage. [What to do →](https://myna.sh/errors/plan-limit-reached) | | `RATE_LIMITED` | 429 | Rate limited | Too many requests in the window. The response carries a Retry-After header. [What to do →](https://myna.sh/errors/rate-limited) | | `SCHEMA_CHANGE_DESTRUCTIVE` | 409 | Destructive schema change | The schema push removes a field, narrows a type, or changes a key — a change that can drop stored data. It is refused rather than applied. [What to do →](https://myna.sh/errors/schema-change-destructive) | | `PUBLISH_VALIDATION_FAILED` | 422 | Publish validation failed | The change set did not validate at publish time. The details object lists every failure across the whole set, including cross-entry problems a single write cannot see: a broken reference, a duplicate slug, a policy rule. [What to do →](https://myna.sh/errors/publish-validation-failed) | | `APPROVAL_REQUIRED` | 409 | Approval required | The project requires approvals on a change set before it publishes, and this one does not have enough of them yet. [What to do →](https://myna.sh/errors/approval-required) | | `CHECKS_FAILED` | 409 | Checks failed | A check the project declared required has not passed. That is either the built-in suite — schema, references, conflicts, slugs, policy — or a check an outside system reports. [What to do →](https://myna.sh/errors/checks-failed) | | `INTERNAL` | 500 | Internal server error | Something failed on our side. This is a bug rather than a request you can correct. [What to do →](https://myna.sh/errors/internal) |