Screenery / API errors / not_found

not_foundHTTP 404

Not found.

What to do

Check the path: org, project, asset and ref must all exist and be spelled exactly. A private resource answers this way too when the caller may not see it, so a 404 on a private asset can mean the wrong credential rather than the wrong name.

What the response looks like

{
  "error": {
    "code": "not_found",
    "message": "Not found.",
    "doc": "https://app.screenery.dev/errors/not_found",
    "request_id": "req_01j…"
  }
}

Every code

Every error from the Screenery API and the delivery CDN is one JSON body, the same shape on every route (spec §13): { "error": { "code", "message", "doc", "request_id" } }. code is stable — a client may branch on it forever — and doc links to that code's page here. Quote request_id (also sent as the x-screenery-request-id header) when reporting a problem.

invalid_request400

The request was malformed.

Check that the body is valid JSON, every required field is present and each identifier follows the spec §1 grammar. The message names what failed.

unauthorized401

Missing or invalid credentials.

Send a credential of the right kind for this route: a publish token to push, a read token to read a private asset, a session for the console. The response never says which check failed; if the credential may have been revoked, issue a new one from the console.

forbidden403

This credential may not perform that action.

The credential is valid but its role or kind does not allow this write. Use one with the needed role, or ask an org admin to grant it. Reads of private resources never answer this way; they answer not_found.

not_found404

Not found.

Check the path: org, project, asset and ref must all exist and be spelled exactly. A private resource answers this way too when the caller may not see it, so a 404 on a private asset can mean the wrong credential rather than the wrong name.

method_not_allowed405

Method not allowed.

The route exists but not for this HTTP method. The Allow header lists the methods it accepts.

conflict409

The request conflicts with the current state.

Something already holds this name, the name is tombstoned, or the write would move a channel backwards. Read the current state, then retry with a different name or a newer build.

upload_incomplete409

Some declared objects are missing or do not match their hash.

Re-upload only the objects the files list names, then call finalize again. The CLI does this on its own; a hand-written client should retry those uploads, not the whole build.

unsupported_media415

Some uploaded objects are not an allowed media type.

The files list says which object and why: not an allowlisted type by its magic bytes, an SVG, or past the dimension cap. Fix the file and push again; no retry changes the bytes.

limit_exceeded429

A plan limit was exceeded.

The envelope carries limit and current. Prune old builds or assets, or raise the plan. Retrying without changing anything gets the same answer.

rate_limited429

Too many requests.

Wait the number of seconds in the Retry-After header, then retry with backoff. The CLI already does this.

not_implemented501

Not implemented in this release.

The route is part of the URL grammar but not of this release. Nothing on the client side fixes it; the route will answer once a release ships it, and the CLI and MCP server only call routes that exist.

internal500

Something went wrong.

A fault on our side. Retry once with backoff; if it persists, report the request_id from the envelope (also in the x-screenery-request-id header) so the failure can be found in the logs.