# Errors

URL: /code/api/error-catalog · Id: `page:code/api/error-catalog`

> Every StartupBuilder error type, with its status, cause, and fix.

Every [StartupBuilder](/code/builders/startup) error is an RFC 9457 [Problem](/business/nouns/problem) whose `type` URL names its cause and fix.

### Shape
Every error is an RFC 9457 problem. Its `type` is the URL of its page.

```json
{
  "type": "https://startupbuilder.dev/errors/not-found",
  "title": "Not found",
  "status": 404,
  "detail": "No record, Noun, or Verb exists at the path, or the caller cannot see it.",
  "fix": "Check the namespace and the id, or search for the record first.",
  "instance": "https://api.sb/acme.com/actions/action_1"
}
```

| Key | Holds |
| --- | --- |
| `type` | The error page: `https://startupbuilder.dev/errors/<slug>`. |
| `title` | The error, in a few words. |
| `status` | The HTTP status. |
| `detail` | What went wrong in this call. |
| `fix` | What to change before retrying. |
| `next` | The call to make next, when there is one. |
| `instance` | The Action the error ended. |
| `requestId` | The request, as the request log names it. |

The CLI prints the same `type` URL and exits `1` or `2`. The SDK throws the Action with the problem as its `error`.

### Catalog
| Error | Status | Cause | Fix |
| --- | --- | --- | --- |
| [Missing key](/code/api/errors/missing-key) | None. | The Startup root file leaves out a key it requires, such as the Startup’s name. | Add the key named in the error to the root file, then push again. |
| [Not literal](/code/api/errors/not-literal) | None. | A key in the Startup root file is computed by a loop, a call or an expression, so it cannot be parsed. | Write the value as a literal or a Template spread; move code that has to run into code/. |
| [Setting set twice](/code/api/errors/setting-set-twice) | None. | A Setting is set both in the Startup root file and in the Settings file, so its value has two homes. | Keep the Setting in one file and delete it from the other, then push again. |
| [Wrong type](/code/api/errors/wrong-type) | None. | A key in the Startup root file holds a value of another type than the key takes. | Change the value to the type the key reference lists, then push again. |
| [Invalid input](/code/api/errors/invalid-input) | `400` | The input does not match the schema of the operation. | Read the schema of the operation, then send every required field with the right type. |
| [Mode not allowed](/code/api/errors/mode-not-allowed) | `400` | The call asks for a Mode the Verb does not accept. | Call the Verb in its default Mode, or in another Mode its reference lists. |
| [Unauthorized](/code/api/errors/unauthorized) | `401` | The request carries no key, or its key is expired or revoked. | Sign in again, or send a current key as a bearer token. |
| [Payment required](/code/api/errors/payment-required) | `402` | The operation is part of an Offer the caller has not accepted or paid for. | Accept the Offer named in the response, then retry the call. |
| [Forbidden](/code/api/errors/forbidden) | `403` | The key is valid, but its scopes do not allow this operation. | Use a key whose scopes cover the operation, or ask an owner of the namespace to grant them. |
| [Limit exceeded](/code/api/errors/limit-exceeded) | `403` | The call went over what the caller is allowed, and the approval it waited for was refused. | Ask an owner of the namespace to raise the allowance, or call again within it. |
| [Not found](/code/api/errors/not-found) | `404` | No record, Noun, or Verb exists at the path, or the caller cannot see it. | Check the namespace and the id, or search for the record first. |
| [Card program pending](/code/api/errors/card-program-pending) | `409` | The card program of the Startup’s owner of record awaits its grant, so no Card can be issued. | Call again once the program is granted; nothing on the Startup’s side changes. |
| [Charges disabled](/code/api/errors/charges-disabled) | `409` | Stripe disabled charges on the Startup’s payment account because a requirement passed its deadline. | Have the owner of record complete the open requirement Task; charges and paid Offers resume on re-enable. |
| [Conflict](/code/api/errors/conflict) | `409` | The record changed since it was read, so the write would overwrite a newer version. | Read the record again, then retry the write against its current state. |
| [Idempotency mismatch](/code/api/errors/idempotency-mismatch) | `409` | The idempotency key already names an Action with a different operation or input, so nothing runs. | Send a new idempotency key for the new request, or resend the original input to read the first Action. |
| [Below contribution floor](/code/api/errors/below-contribution-floor) | `422` | The median Customer’s Cost leaves less than the Startup’s target margin at this Price. | Raise the Price to the floor the error names, or grant fewer Entitlements. |
| [Refused](/code/api/errors/refused) | `422` | The record is not in a state that allows this Verb, so the call is refused. | Read the record, run the Verb that moves it to an allowed state, then retry. |
| [Rate limited](/code/api/errors/rate-limited) | `429` | The caller sent more requests than its rate allows. | Wait the number of seconds in the `Retry-After` header, then retry. |
| [Not live](/code/api/errors/not-live) | `503` | The call uses a live key, and the Startup has no deployed Version. | Use a test key, or deploy a Version of the Startup, then retry. |