Skip to content
AdCrunch
Esc
↑↓navigate↵open⌘Jpreview
On this page

Errors

The one shape of an AdCrunch failure, the field to branch on, the order of the checks, and the codes that more than one operation sends.

The shape of a failure

Each AdCrunch failure has the same JSON body, in each of the four APIs:

{
  "error": "not_found",
  "message": "Skill not found"
}
  • error is a stable code. Branch on it. A code does not change for a given failure.
  • message is for a person. Show it, or log it. AdCrunch rewrites a message when it can say it better, so never branch on it.

Some failures add a field that tells you what to do next:

error Added field What it holds
revision_mismatch currentRevision The revision that the row holds now. See Edit without overwriting.
slug_conflict slug The slug that is already taken.
unsupported_type allowed Each media type that the operation accepts. Only when you reserve a Document.
invalid_request issues One entry for each field that does not match. See A request that does not match.
too_large sizeBytes, limitBytes The size of the stored file, and the limit. Only when you finalize a Document.
live_read_unsupported, provider_not_connected, provider_error provider The provider of the advertiser. See Live reads.
provider_error platformError The error object of the provider, with no change.

The page of each operation lists each status and each code that it sends. The overview lists each operation.

A request that does not match

A request that does not match the schema of its operation answers 400 with error: "invalid_request". The field is missing, it has the wrong type, or the body is not valid JSON. issues names each field. This is POST /assets/uploads with no filename:

{
  "error": "invalid_request",
  "message": "The request does not match the schema. Read issues for each field.",
  "issues": [
    {
      "in": "body",
      "path": "/filename",
      "message": "Invalid input: expected string, received undefined"
    }
  ]
}
  • in is the part of the request that holds the field: body, query, params, headers or cookie.
  • path is a JSON Pointer into that part. An empty string is the whole part, for example a body that is not valid JSON.
  • message is for a person, as above.

The answer never repeats what you sent. The schema of each operation is on its page.

400 and 422

  • 400: the request does not have the right shape. invalid_request is the code. Correct the request.
  • 422: the request has the right shape, and AdCrunch refuses what it says. The code says why, for example invalid_amount or advertiser_not_owned.

The order of the checks

Each operation checks the API key first, then the permission, then the request. So a request with no key and a bad body answers 401, and a key without the permission answers 403, before the body is read against the schema.

There is one exception. A body that is not valid JSON answers 400 before the API key is checked, because the body is read before any check runs.

A path that does not exist

A path that no operation answers gets 404 with error: "not_found", the same code as a thing that does not exist. The message tells the two apart.

Changed on 2026-09-24. Before this date, a request that did not match the schema answered 422 with the shape of the framework, and a path that did not exist answered the plain text NOT_FOUND. Neither had an error field. In Observe, Context, and Assets, the schema was checked before the API key.

The data of another organization

The API never tells you whether a thing exists in another organization.

  • Mutations, Context, and Assets answer 404 with error: "not_found". A thing that never existed gets the same answer. So these APIs never answer 403 for it.
  • Observe answers 200. A list is empty, and a read of one entity has an empty body. In Observe, an advertiser of another organization is not a failure.

Codes that more than one operation sends

Status error Meaning What to do
400 invalid_request The request does not match the schema. issues names each field. Every operation that takes input. Correct the request.
400 invalid_cursor AdCrunch cannot use the cursor: it cannot read it, or the cursor belongs to a different query. Every list of Observe, Mutations, Assets and Context. Send the nextCursor of the previous answer, with no change.
401 unauthorized No API key, or a key that does not resolve. See Authentication.
403 forbidden The key does not hold the permission. See Authentication.
404 not_found The thing does not exist in your organization, or no operation answers the path. Do not retry.
409 revision_mismatch Somebody wrote first. Read again, apply your change, and send it again.
409 slug_conflict Another row in your organization has that slug. Choose a different slug.
413 too_large The stored file is larger than the limit. AdCrunch deleted it. See Upload a file.
415 unsupported_type The stored file has a type that AdCrunch does not accept. AdCrunch deleted it. See Upload a file.
415 type_mismatch The bytes of a stored Asset are a different type from the Content-Type of its upload. AdCrunch deleted it. Upload again with the real Content-Type.
415 unreadable The stored Asset is no accepted type, or it ends before its header does. AdCrunch deleted it. Upload an intact file of an accepted type.
422 advertiser_not_owned That advertiser is not one of your organization. Use an advertiserId of your organization.

Live reads

Every Observe operation whose path names an advertiser, such as GET /observe/{advertiserId}/campaigns, is a live read: AdCrunch asks the provider itself, and not what AdCrunch holds. A live read can fail in three ways, and each needs a different action:

Status error Meaning What to do
501 live_read_unsupported AdCrunch cannot read this resource live from this provider. This does not change. Read the stored copy: GET /observe/campaigns?advertiserId=acc_….
409 provider_not_connected The connection to the provider does not work. A person must connect the advertiser again. The stored read, GET /observe/campaigns?advertiserId=acc_…, still answers what AdCrunch holds.
502 provider_error The provider refused the request, or did not answer. Retry. This failure is often temporary.

What each provider supports lists which resource each provider can read live.

Was this page helpful?