> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# SPI error list

> Look up the error codes the SPI Pix rail returns, the HTTP status each one carries, and what to do about it.

**Error format**

The SPI API returns errors as RFC 9457 problem details with the `application/problem+json` media type:

<CodeGroup>
  ```json JSON theme={null}
  {
    "type": "https://errors.lerian.studio/v1/SPI-1002",
    "title": "Unprocessable Entity",
    "status": 422,
    "detail": "bacen rejected payment",
    "code": "SPI-1002",
    "correlationId": "req-7a3f9c2e"
  }
  ```
</CodeGroup>

**Field definitions**

* **`type`** – A URI that identifies the error in the Lerian error catalog, built as `https://errors.lerian.studio/v1/<code>`. A response with no `code` carries the RFC default `about:blank`.
* **`title`** – The HTTP status text (for example, `Unprocessable Entity`).
* **`status`** – The HTTP status code.
* **`detail`** – A human-readable explanation for this occurrence. The text varies with the occurrence, so branch on `code`.
* **`code`** – A stable identifier for the condition. A request the rail refused before it reached a handler carries no `code`. This API uses two vocabularies here: the rail's own `SPI-NNNN` codes, and the Pix key directory tokens described further down.
* **`errors`** – Optional list of per-field validation details, each with a `message`, a `location`, and the offending `value`.
* **`correlationId`** – The request-scoped correlation identifier. Quote this value in a support request.

For `5xx` responses, the rail replaces `detail` with `internal error` so internal causes stay inside. Use `code` to branch programmatically.

## Rail codes

***

The `SPI-NNNN` codes name conditions the SPI rail itself judges. The digit after the prefix groups them: `0` input, `1` rail transport, `2` authorization, `3` processing, `4` rate and quota, `9` fallback.

Four codes carry more than one status, because the condition they name has more than one shape on this rail. Each appears below under each status it can arrive with.

When BACEN refuses a payment, the refusal carries the network's own ISO 20022 status reason. `RJCT` is the one that names a refusal. On the API surface, `SPI-1002` is the code for that refusal. To find which payments the network refused, read the rejected payments report. It lists each one by terminal status and end-to-end id.

### 401: Unauthenticated

***

| `code`   | Description                                                                                   | `detail`                        |
| -------- | --------------------------------------------------------------------------------------------- | ------------------------------- |
| SPI-2001 | The request does not identify a principal. The bearer is missing, malformed, or unrecognized. | authenticated actor unavailable |

### 403: Forbidden

***

| `code`   | Description                                                     | `detail`  |
| -------- | --------------------------------------------------------------- | --------- |
| SPI-2002 | The caller is identified and is not authorized for this action. | forbidden |

### 404: Not found

***

| `code`   | Description                                    | `detail`          |
| -------- | ---------------------------------------------- | ----------------- |
| SPI-0010 | The resource the request names does not exist. | payment not found |

### 409: Conflict

***

| `code`   | Description                                                                              | `detail`                                |
| -------- | ---------------------------------------------------------------------------------------- | --------------------------------------- |
| SPI-0011 | A resource with this identity already exists.                                            | participant already exists              |
| SPI-3006 | The resource's current lifecycle state refuses the operation.                            | payment is not eligible for return      |
| SPI-3007 | Another writer changed the resource between your read and your write. Re-read and retry. | participant status changed concurrently |

### 413: Payload too large

***

| `code`   | Description                                                                                       | `detail`                                                          |
| -------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| SPI-0003 | The uploaded remessa exceeds what the batch file channel processes in one upload. Split the file. | the remessa exceeds the 5 MB this channel processes in one upload |

### 422: Unprocessable

***

| `code`   | Description                                                                                                                                  | `detail`                               |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| SPI-0001 | A required input is missing or empty.                                                                                                        | return reason is required              |
| SPI-0002 | A field carries the wrong format.                                                                                                            | mode must be FULL or INCREMENTAL       |
| SPI-0003 | A business rule refused the request.                                                                                                         | invalid payment request                |
| SPI-0011 | The charge surface refuses a duplicate identifier, such as a txid another charge already holds.                                              | charge already exists                  |
| SPI-1002 | BACEN rejected the message.                                                                                                                  | bacen rejected payment                 |
| SPI-1011 | The Pix key directory rejected the request. Where the directory named the reason, the token arrives instead. See the directory tokens below. | bacen dict rejected request            |
| SPI-3002 | Internal processing refused to route the request.                                                                                            | operation routing decision unavailable |
| SPI-3006 | The charge or batch lifecycle refuses the operation.                                                                                         | invalid charge state transition        |
| SPI-4001 | The participant's own operation quota is exhausted.                                                                                          | quota limit exceeded                   |

### 429: Too many requests

***

| `code`   | Description                                                                                                                                                                                        | `detail`                      |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| SPI-4001 | The rail's BACEN-outbound quota is exhausted, or the Pix key directory throttled the request. A directory throttle carries the wait in the `Retry-After` header when the directory prescribed one. | bacen outbound quota exceeded |

### 500: Server error

***

| `code`   | Description                                                                                 | `detail`       |
| -------- | ------------------------------------------------------------------------------------------- | -------------- |
| SPI-9000 | An unexpected internal failure. Retry, then contact support with the `correlationId` value. | internal error |

### 502: Bad gateway

***

| `code`   | Description                                                                       | `detail`       |
| -------- | --------------------------------------------------------------------------------- | -------------- |
| SPI-1005 | Communication with BACEN failed for a reason the rail could not classify further. | internal error |

### 503: Service unavailable

***

These codes name dependency conditions. Back off and retry.

| `code`   | Description                                                                                        | `detail`       |
| -------- | -------------------------------------------------------------------------------------------------- | -------------- |
| SPI-1001 | The BACEN transport is unavailable.                                                                | internal error |
| SPI-1004 | Transport security validation failed. The rail refused to send on a channel it could not validate. | internal error |
| SPI-1010 | The Pix key directory is unavailable, for maintenance or outside its service window.               | internal error |
| SPI-3001 | Persistence or event publication is unavailable.                                                   | internal error |
| SPI-9001 | A downstream dependency the request needs is unavailable.                                          | internal error |

### 504: Gateway timeout

***

| `code`   | Description                                                                                                          | `detail`       |
| -------- | -------------------------------------------------------------------------------------------------------------------- | -------------- |
| SPI-1003 | BACEN did not answer within the rail's window. The outcome is undetermined, so query the resource before you resend. | internal error |

## Pix key directory tokens

***

The Pix key directory keeps its own error vocabulary, and the rail forwards it. A directory refusal reaches you with the directory's own token in `code` and the directory's own HTTP status in `status`. The `type` URI carries the same token as its last segment.

This vocabulary belongs to the directory, so treat it as open. Handle a token you do not recognize by its `status`, and read the token itself as the reason. The tables below cover the tokens the rail handles today, across key registration, key lookup, key deletion, and the claim operations.

<Note>
  A rate-limit refusal from the directory reaches you as `SPI-4001` with HTTP 429. When the directory prescribed a wait, the response carries it in `Retry-After`. See the rail codes above.
</Note>

### General

***

| `code`                  | Description                                                          | Status |
| ----------------------- | -------------------------------------------------------------------- | ------ |
| Forbidden               | The request violates an authorization rule.                          | 403    |
| BadRequest              | The request format is invalid at the schema level.                   | 400    |
| NotFound                | The entity the request names does not exist.                         | 404    |
| Gone                    | The resource existed and is not available.                           | 410    |
| InternalServerError     | An unexpected condition on the directory side.                       | 500    |
| ServiceUnavailable      | The directory is unavailable, for maintenance or outside its window. | 503    |
| RequestSignatureInvalid | The request digital signature is invalid.                            | 400    |
| RequestIdAlreadyUsed    | The same RequestId came back with different parameters.              | 400    |
| InvalidReason           | The reason given for the operation is invalid.                       | 400    |
| ParticipantInvalid      | The participant cannot take part in this operation.                  | 400    |
| TaxIdNumberBlocked      | The CPF or CNPJ is blocked by judicial order.                        | 400    |

### Key registration

***

| `code`                                  | Description                                                                               | Status |
| --------------------------------------- | ----------------------------------------------------------------------------------------- | ------ |
| EntryInvalid                            | The fields that create or update the entry are invalid.                                   | 400    |
| EntryLimitExceeded                      | The account holds the maximum number of keys already.                                     | 400    |
| EntryAlreadyExists                      | The key is registered already for this participant and owner.                             | 400    |
| EntryCannotBeQueriedForBookTransfer     | The key belongs to the same PSP. Resolve it internally rather than through the directory. | 400    |
| EntryKeyOwnedByDifferentPerson          | A different person owns the key. Open a possession claim.                                 | 400    |
| EntryKeyInCustodyOfDifferentParticipant | The same owner holds the key at another PSP. Open a portability claim.                    | 400    |
| EntryTaxIdNumberByDifferentOwner        | The CPF or CNPJ on the entry differs from the key owner's.                                | 400    |
| EntryLockedByClaim                      | An active claim locks the entry, so it cannot be deleted.                                 | 400    |
| EntryBlocked                            | A judicial order blocks the entry.                                                        | 400    |

### Key claims

***

| `code`                           | Description                                                         | Status |
| -------------------------------- | ------------------------------------------------------------------- | ------ |
| ClaimInvalid                     | The fields that create or update the claim are invalid.             | 400    |
| ClaimTypeInconsistent            | The claim type is inconsistent with the entry's state.              | 400    |
| ClaimKeyNotFound                 | The claimed key does not have a registered entry.                   | 404    |
| ClaimAlreadyExistsForKey         | An active claim exists for the key already.                         | 400    |
| ClaimResultingEntryAlreadyExists | The resulting entry exists already for the claimant.                | 400    |
| ClaimOperationInvalid            | The claim's status forbids the operation you requested.             | 400    |
| ClaimResolutionPeriodNotEnded    | The resolution period has not ended, so the operation is premature. | 400    |
| ClaimCompletionPeriodNotEnded    | The completion period has not ended, so finalizing is premature.    | 400    |

## BR Code file rejections

***

The BR Code batch file channel answers a submitted remessa line by line. An accepted line settles. A refused line carries a three-digit rejection code. It also carries the field name and description that the Pix scheme publishes for that code. Your reconciliation maps the answer against the scheme's own error sheet.

Two rejections refuse a line before any business rule runs, so they are the first ones a new integration meets. `063` (Cadastro, Cliente nao cadastrado) says the file header names a recebedor that this deployment does not hold a registered profile for. `096` (Registro, Inválido) says the scheme refused the record and publishes no more specific code for the field at fault. A record of the wrong length is one of these.

Four more cover the two identifiers that most lines carry. `012` (Chave pix, Chave inválida) says the line collects on a Pix key that this deployment does not hold a registered recebedor for. `014` (Chave pix, Não é compatível com o cnpj ou agência e conta informada) names a key registered to another recebedor. The file header resolves to a different one. `016` (Identificador (txid), Em duplicidade) says the txid repeats. `017` (Identificador (txid), Inválido ou não encontrado) says the movement names a charge this rail does not hold.

The scheme's error sheet publishes many more codes. The channel renders the subset that its own refusals map onto. Each rejected line names its field, so read the field name first and the code second.
