Skip to main content
Every failure Cortex returns has the same shape: an RFC 9457 problem document, sent as application/problem+json. There is no second error format anywhere in the product, so one way of reading an error works on every surface, from Cortex Chat to Cortex Code to the Cortex CLI. This page explains the fields of a problem document, which of them are a contract and which are only prose, how to get from an error to the page that explains it, and what retrying does and does not fix. It then lists every code Cortex emits, with its HTTP status, whether retrying helps, and the message the product shows for it.

The shape of a problem document

How to read one

Read the four always-present fields in this order, and you have everything you need.
  • code tells you what happened. The same code means the same thing on every surface and in every product, which is why it is the only field worth writing logic against.
  • type tells you where it is explained. The problem type base is https://docs.cortex.foundation/problems, and type is that base plus /{code}. So a quota_exceeded failure carries type: "https://docs.cortex.foundation/problems/quota_exceeded", and following that URL lands on the page for it. Every code below has one.
  • status tells you the class of the failure, and is the fastest way to sort a pile of errors into “my request was wrong”, “I am not allowed”, “I am going too fast” and “Cortex broke”. It is not precise enough to act on: two different 429s mean two different things.
  • request_id tells you which request this was. One id identifies one failed request.
detail is the part that varies. The other fields are the same for every occurrence of a code, while detail describes this one occurrence, and it is written for a person reading raw output, not for a user interface. It may name a Cortex surface or a specific resource. Treat it as diagnostic text: log it, and do not build anything on its wording.

What is safe to show a user

The web app never renders the wire title or detail. It looks the code up in its own message catalogue and shows that instead. Anything you build against these documents should do the same.
  • Write your own copy per code. The page for each code explains the situation in product language.
  • Do not render detail as the primary message. It is not the user’s message.
  • Exactly three codes may show detail as a secondary line: validation_failed, bad_request and invalid_state. Even there it supplements the message rather than being it.
  • internal deliberately carries nothing. A 500 arrives with a status, the generic title and a request_id, and never a detail, field errors or extensions. The reference id is the only actionable thing in it, and the product’s own copy says so.

Errors never name a vendor

Before any message reaches a user, an internal service name is converted into product language. What you will see is a Cortex surface, in one of two sentences: “<phrase> is temporarily unavailable.” or “<phrase> did not respond in time.” The phrases are product-facing and stable enough to recognise: Sign-in, The assistant, The audio service, Connected apps, The plugin service, The payments service, The memory service, The bot computer, The Code runtime, The remote host, Cortex Security, The model catalogue, Image generation, Document export, Literature search, Origin detection, and This feature as a fallback. No subprocessor is ever named in an error.

The reference id

request_id is always present, and it is the one value in a problem document that is designed to be shown to a user. In the product it appears at the bottom of an error card as Reference followed by the id. That string is the same value as request_id in the document behind the card.
1

Read the error card

The line beginning Reference holds the id.
2

Copy it before you retry

A retry produces a new id. The one that matters is the id from the request that failed.
3

Quote it when you get in touch

One id identifies one request, which is what lets support find it. For an internal failure the copy already asks for this: “This was not your fault and it has been recorded. Quote the id below if you get in touch.”

Rejected fields

validation_failed is the only code that carries per-field detail, as an errors array. Each entry has three keys. The product renders its own sentence per field code: “This is longer than allowed.”, “This is required.”, “This is not one of the accepted values.”, and “This was not accepted.” for anything it does not recognise. Showing the field errors next to the fields they point at is the whole value of this code, so prefer that over a single summary message.

Typed extras, by code

Some codes carry extra members alongside the standard fields. They are typed, so you can rely on them where the code says they appear.

Every code Cortex emits

Twenty-four codes, each with its own page. The What the product shows column is the heading a user actually reads in the app, so it is the fastest way to match an error you were sent a screenshot of to the code behind it. Grouped by status, in the order you are most likely to meet them: A retired capability answers gone rather than pretending to work or disappearing into a 404, so gone is worth handling even if you have never seen it.

Retrying

Seven codes are retryable: conflict, rate_limited, internal, upstream_failure, upstream_timeout, service_unavailable and no_capacity. For every other code the same request will fail the same way, and the request, the plan or the state has to change first.
  • rate_limited carries retry_after_seconds. Wait that long, then back off. The product shows either “You can try again in” a label, or “You can try again now.”
  • conflict is the one retryable 4xx. Something changed underneath you, so reload to pick up the current version and apply your change again.
  • no_capacity is specific to one model. Try again shortly, or pick another model. When the document carries a fallback_model, the product offers Continue with that model as a button, which is a choice you make rather than a substitution made for you.
  • internal, upstream_failure, upstream_timeout and service_unavailable are ours. Retry, keep the reference id, and check System status if it repeats.
Two of the three 429s are not retryable, which is the most common mistake made against this contract.quota_exceeded means a plan window is used up. It carries resets_at and retry_after_seconds, but those say when the window rolls over, not when to retry the same call. Waiting for the reset or changing plan is what fixes it.concurrency_limit_reached means too much is already running on the account. The sensible action is to wait for a run to finish, which frees a slot, but retrying immediately does not help.

When it was not your fault

Three codes are always Cortex’s own problem: internal, upstream_failure and upstream_timeout. The product says so in as many words, because a user who has just lost a turn deserves to know whether to keep trying. Nothing is expected of you beyond keeping the reference id. A request that reached the assistant and came back an error often succeeds on a retry; one that timed out was abandoned rather than left hanging, and a shorter prompt usually gets through.

When there is no problem document

If the request never reached Cortex, there is nothing to read. The product says You appear to be offline with “Nothing was sent. This works again as soon as the connection is back.”, or The request could not be completed with “Something went wrong before the request finished. Trying again usually works.”
A network failure is not a problem document. There is no code and no request_id to quote for one, so a report of “it just failed” with no reference id is usually this, not a Cortex error.

Codes that are not problem codes

Cortex Security records its own reasons when a pull-request review cannot run: upstream_unconfigured, no_model_available, app_not_configured, diff_unavailable, nothing_to_review, installation_suspended and review_incomplete. These are stored with the review and rendered as a sentence on the review itself. They are not HTTP problem codes, they never appear in a problem document, and they have no page in the catalogue. Security troubleshooting covers each of these situations and what to do about it.

Problem catalog

Every code with its status and retry answer, and a page per code.

Limits and quotas

The windows behind quota_exceeded, and what resets when.

Troubleshooting

What a message you see in the product means, by symptom.

System status

Whether something is down right now, which this page cannot tell you.
  • Models for the model names behind no_capacity and fallback_model.
  • Security and privacy for what is kept in a log alongside a reference id.