> For the complete documentation index, see [llms.txt](https://docs.startrail.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.startrail.io/issue-transfer-api/issue-and-transfer-srr-nft/errors.md).

# Errors & Troubleshooting

This page catalogues **every error** returned by the Commerce REST endpoints used to issue, transfer and manage SRRs:

* `POST /port/api/v1/commerce/srrs` — [Issue & Transfer](/issue-transfer-api/issue-and-transfer-srr-nft/issue-and-transfer.md)
* `POST /port/api/v1/commerce/collection` — [Create Collection](/issue-transfer-api/collection/create-collection.md)
* `POST /port/api/v1/commerce/signedUrls` — [Request Signed URL](/issue-transfer-api/issue-and-transfer-srr-nft/request-signed-url-for-upload-download-files.md)
* `POST /port/api/v1/commerce/fileMetadata` — [File Information Metadata](/issue-transfer-api/issue-and-transfer-srr-nft/file-information-metadata.md)

{% hint style="info" %}
Replace `<base_url>` with the environment you are calling — see [URL per environment](/readme/url-per-environment.md). All examples below use the JSON response envelope described next.
{% endhint %}

## Response envelope

Errors come back in one of **two shapes**:

{% tabs %}
{% tab title="Request-level" %}
A single error for the whole request (bad headers, invalid body, duplicate request, internal error):

```json
{
  "statusCode": 400,
  "message": "Address not found: 0xabc...123"
}
```

`message` is either a **string** or an **array of strings** (when multiple validation rules fail at once).
{% endtab %}

{% tab title="Per-SRR (issuance)" %}
For `POST /srrs`, issuance problems are reported **per payload entry** under `message.results[]`, keyed by your `externalId`:

```json
{
  "statusCode": 400,
  "message": {
    "results": [
      {
        "status": "failed",
        "externalId": "c0456840-5bdf-4375-a6ce-106697b7dfb7",
        "message": "DUPLICATE_METADATA"
      }
    ]
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
**Issuance is atomic.** In a bulk `POST /srrs`, if **any** entry fails, the **entire batch is cancelled** — no SRR in the request is issued. Fix the failing entry and resubmit the whole payload.
{% endhint %}

## Status code overview

| Status                      | Meaning                                                                                 | Typical causes                                                                                   |
| --------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `400` Bad Request           | The request was rejected before/at validation, or an SRR entry failed an issuance check | Invalid metadata, bad address, duplicate request, [per-SRR codes](#per-srr-issuance-error-codes) |
| `401` Unauthorized          | Authentication failed                                                                   | Missing/invalid `commerce-api-key` or `issuer-address`                                           |
| `404` Not Found             | A referenced file does not exist in storage                                             | `POST /fileMetadata` for a file that was never uploaded                                          |
| `500` Internal Server Error | A downstream (Startrail / signing / storage) step failed                                | Quota/NFC limits, `STARTRAIL_ERROR`, storage instability                                         |

{% hint style="info" %}
**Acceptance ≠ minting.** A `201` only means the request was accepted and queued (`status: "waiting_for_mining"`). Blockchain-level failures (e.g. funds, nonce, gas) happen **after** acceptance and are reported via the [webhook](/issue-transfer-api/issue-and-transfer-srr-nft/webhook-setup.md), not in the HTTP response. See [Asynchronous (post-acceptance) failures](#asynchronous-post-acceptance-failures).
{% endhint %}

## Errors by status

{% tabs %}
{% tab title="401" %}
Returned by **all** Commerce endpoints when the API-key / issuer headers are missing or do not match.

```json
{ "statusCode": 401, "message": "Missing header" }
```

```json
{ "statusCode": 401, "message": "API Key is not valid for 0xA6E6a9E20a541680a1D6E1412f5088AefBF58a22" }
```

| Message                              | Cause                                                      | Fix                                             |
| ------------------------------------ | ---------------------------------------------------------- | ----------------------------------------------- |
| `Missing header`                     | `commerce-api-key` or `issuer-address` header absent/empty | Send both headers on every request              |
| `API Key is not valid for <address>` | The key does not resolve to the supplied `issuer-address`  | Use the API key that belongs to that issuer LUW |
| {% endtab %}                         |                                                            |                                                 |

{% tab title="400" %}
Two families: **request-level** (rejected outright) and **per-SRR** (`message.results[]`).

```json
// Request-level — metadata fails the JSON schema
{
  "statusCode": 400,
  "message": [
    "payload.0.metadata is invalid. Check it against the metadata JSON schema. Details:  should have required property 'title' ({\"missingProperty\":\"title\"}).",
    "payload.0.artistAddress must be a valid Ethereum addresses",
    "payload.0.externalId should not be empty"
  ]
}
```

```json
// Per-SRR — an entry failed an issuance check
{
  "statusCode": 400,
  "message": {
    "results": [
      { "status": "failed", "externalId": "c0456840-...", "message": "DUPLICATE_CHIP" }
    ]
  }
}
```

See [Request-level errors](#request-level-errors-400) and [Per-SRR codes](#per-srr-issuance-error-codes).
{% endtab %}

{% tab title="404" %}
Only from `POST /fileMetadata`, when one or more requested files do not exist in storage. The body lists the missing files:

```json
[
  { "index": 0, "filePath": "0xA6E6.../not-found.jpg" }
]
```

| Cause                                                                                  | Fix                                                                                                                                                                                           |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Referencing a file that was never uploaded, or whose name/category differs from upload | Upload via [`/signedUrls`](/issue-transfer-api/issue-and-transfer-srr-nft/request-signed-url-for-upload-download-files.md) first; query with the exact `filename` + `category` used at upload |
| {% endtab %}                                                                           |                                                                                                                                                                                               |

{% tab title="500" %}
A downstream step failed. The message usually carries a `STARTRAIL_ERROR:` prefix wrapping the underlying reason.

```json
{ "statusCode": 500, "message": "STARTRAIL_ERROR: LUW missing NFC tag!" }
```

```json
{ "statusCode": 500, "message": "STARTRAIL_ERROR: Quota limit exceeded!" }
```

| Message (contains)                                              | Cause                                                                                                             | Fix                                                                               |
| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `STARTRAIL_ERROR: Quota limit exceeded!`                        | The issuer LUW's SRR issuance quota is exhausted                                                                  | Top up the issuance quota for the LUW                                             |
| `STARTRAIL_ERROR: LUW missing NFC tag!`                         | NFC tag UIDs in the request exceed the LUW's NFC-tag allowance — see [NFC tag errors](#nfc-tags-and-quota-errors) | Reduce chips in the request or top up NFC-tag allowance                           |
| `STARTRAIL_ERROR: <other>`                                      | A forwarded Startrail / signing failure                                                                           | Retry; if it persists [contact us](https://startbahn.io/contact) with the message |
| `UNKNOWN_ERROR`                                                 | Unclassified server error                                                                                         | Retry; contact support if persistent                                              |
| `It may happen if the network to bucket storage is not stable.` | Transient storage error on `/signedUrls` or `/fileMetadata`                                                       | Retry the request                                                                 |
| {% endtab %}                                                    |                                                                                                                   |                                                                                   |
| {% endtabs %}                                                   |                                                                                                                   |                                                                                   |

## Per-SRR issuance error codes

These appear in `message.results[*].message` for `POST /srrs` (HTTP `400`). Each is tied to the `externalId` of the failing entry.

| Code                    | Meaning                                                       | How to fix                                          |
| ----------------------- | ------------------------------------------------------------- | --------------------------------------------------- |
| `DUPLICATE_METADATA`    | An SRR with identical metadata already exists for this artist | Change the metadata, or skip — it is already issued |
| `DUPLICATE_CHIP`        | A chip UID in the request is already attached to another SRR  | Remove/replace the duplicated chip UID              |
| `INVALID_CHIP`          | A chip UID is malformed or not accepted                       | Correct the chip UID value(s)                       |
| `DUPLICATE_EXTERNAL_ID` | The `externalId` was already used by a previous issuance      | Use a fresh, unique `externalId`                    |
| `UNKNOWN_ARTIST`        | `artistAddress` is not a known Licensed User Wallet           | Use a valid artist LUW address                      |
| `SRR_NOT_CREATED`       | The SRR could not be created on chain                         | Retry; contact support if it persists               |

{% hint style="info" %}
Because the batch is atomic, a single failed entry fails the whole request. The `results[]` array tells you **which** `externalId` to fix.
{% endhint %}

## Request-level errors (400)

Rejected before issuance begins.

| Message                                                                                                                                                                                                                                                                                                                         | Endpoint(s)                    | Cause                                                                                                                                                                                                                                                                                | Fix                                                                                                                                                                 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<field> is invalid. Check it against the metadata JSON schema. Details: …`                                                                                                                                                                                                                                                     | `/srrs`                        | `metadata` fails the SRR JSON schema                                                                                                                                                                                                                                                 | See [Metadata validation](#metadata-validation-errors)                                                                                                              |
| `Some of the metadata is not defined`                                                                                                                                                                                                                                                                                           | `/srrs`                        | A `payload[]` entry has no `metadata`                                                                                                                                                                                                                                                | Provide `metadata` for every entry                                                                                                                                  |
| `Some metadata is failed to be converted: <reason>`                                                                                                                                                                                                                                                                             | `/srrs`                        | Metadata could not be upgraded to the current schema                                                                                                                                                                                                                                 | Fix the metadata per `<reason>`                                                                                                                                     |
| `Address not found: <addresses>`                                                                                                                                                                                                                                                                                                | `/srrs`                        | `issuer-address` or a `payload[*].artistAddress` is not a known LUW                                                                                                                                                                                                                  | Use valid LUW addresses                                                                                                                                             |
| `File URLs must be Startbahn storage URLs (the finalUrl returned by /commerce/signedUrls) or ipfs:// URLs. Upload the files via /commerce/signedUrls and use the returned finalUrl for: [<externalId>] <field>: <url>`                                                                                                          | `/srrs`                        | A `metadata.thumbnailURL`, `metadata.image`, `metadata.contractTerms.fileURL` or `attachmentFiles[*].url` points at an external host — see [File URLs](/issue-transfer-api/issue-and-transfer-srr-nft/issue-and-transfer.md#file-urls-every-file-must-come-from-the-signed-url-flow) | Upload the file via [`/signedUrls`](/issue-transfer-api/issue-and-transfer-srr-nft/request-signed-url-for-upload-download-files.md) and use the returned `finalUrl` |
| `Metadata file URLs (thumbnailURL, image, contractTerms.fileURL) must be publicly accessible - files in the private bucket cannot be served or published to IPFS. Upload them via /commerce/signedUrls with a public file category (e.g. non_attachment_file) and use the returned finalUrl for: [<externalId>] <field>: <url>` | `/srrs`                        | A `thumbnailURL` / `image` / `contractTerms.fileURL` points at a file uploaded with a **private** category (`certificate`, `for_authenticity`, `installation`)                                                                                                                       | Re-upload with a public category — `non_attachment_file` (recommended) or `artwork` — and use that `finalUrl`                                                       |
| `Metadata file(s) not found in storage. Upload them via /commerce/signedUrls and use the returned finalUrl for: [<externalId>] <field>: <url>`                                                                                                                                                                                  | `/srrs`                        | A `thumbnailURL` / `image` / `contractTerms.fileURL` references a Startbahn URL whose file was never uploaded                                                                                                                                                                        | Upload first via `/signedUrls`                                                                                                                                      |
| `Metadata file(s) not ready for IPFS publication (CID still being calculated). Check readiness via /commerce/fileMetadata and retry for: [<externalId>] <field>: <url>`                                                                                                                                                         | `/srrs`                        | The referenced file is uploaded but its IPFS CID is still computing                                                                                                                                                                                                                  | Poll [`/fileMetadata`](/issue-transfer-api/issue-and-transfer-srr-nft/file-information-metadata.md) until `cid` is present, then retry                              |
| `One or more attachment files were not found in storage. Upload them via /commerce/signedUrls before issuing.`                                                                                                                                                                                                                  | `/srrs`                        | An `attachmentFiles[*].url` is not an uploaded file                                                                                                                                                                                                                                  | Upload first via `/signedUrls`                                                                                                                                      |
| `Attachment hash not ready for <url>. Wait for hash calculation and retry, or check via /commerce/fileMetadata.`                                                                                                                                                                                                                | `/srrs`                        | The file is uploaded but its hash is still computing                                                                                                                                                                                                                                 | Poll [`/fileMetadata`](/issue-transfer-api/issue-and-transfer-srr-nft/file-information-metadata.md) until `hash` is present, then retry                             |
| `Duplicate Request Error: Same requestId already logged`                                                                                                                                                                                                                                                                        | `/srrs`                        | The `requestId` was already used for this issuer                                                                                                                                                                                                                                     | Use a new unique `requestId` (UUID)                                                                                                                                 |
| `Request Content Error: Current request already logged with status <in_progress\|successful>`                                                                                                                                                                                                                                   | `/srrs`                        | An identical payload is already in flight or already succeeded                                                                                                                                                                                                                       | Do not resubmit; read the result via the [subgraph](/subgraph/subgraph.md)                                                                                          |
| `extension is missing` / `space is not allowed`                                                                                                                                                                                                                                                                                 | `/signedUrls`, `/fileMetadata` | `filename` has no extension or contains a space                                                                                                                                                                                                                                      | Use a filename like `cert.pdf` with no spaces                                                                                                                       |

{% hint style="success" %}
**Idempotency.** Send a unique `requestId` (UUID) on every `POST /srrs`. A retried request with the same `requestId` is safely rejected instead of double-issuing.
{% endhint %}

## NFC tags and quota errors

If you attach NFC/IC tags to SRRs, two allowance checks apply to the issuer LUW.

{% hint style="danger" %}
**`STARTRAIL_ERROR: LUW missing NFC tag!`** does **not** mean a tag is unregistered. It means the **number of IC tag UIDs in your request exceeds the LUW's available NFC-tag allowance**.
{% endhint %}

| Error                   | Rule                                                 | Notes                                                                                                                   |
| ----------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `Quota limit exceeded!` | SRR issuance count exceeds the LUW's quota           | Counts SRRs being issued                                                                                                |
| `LUW missing NFC tag!`  | IC tag UID count exceeds the LUW's NFC-tag allowance | **Single request:** that entry's tag count. **Bulk request:** the **sum** of tag UIDs across all entries in the request |

* You do **not** pre-register individual tag UIDs — they are registered via `metadata` at issuance. You only need enough NFC-tag allowance on the LUW beforehand.
* In schema **v2.2**, the IC tag UIDs go in `chipUIDs`, and `startbahnCertICTagUIDs` must be supplied **with the same values** (the two are mutually required). See the recipe and schema:

{% content-ref url="/pages/0jhQ5HkfFA9BLusH5SmK" %}
[Request Payloads & Recipes](/issue-transfer-api/issue-and-transfer-srr-nft/payloads.md)
{% endcontent-ref %}

{% content-ref url="/pages/cfyaLly9LtHuauzFV359" %}
[Version 2.2](/metadata-schema/startrail-registry-srr/version-2.2.md)
{% endcontent-ref %}

## Metadata validation errors

`metadata` is validated against the [SRR JSON schema](/metadata-schema/startrail-registry-srr.md) (version 2.0+). Failures return `400` with a message of the form:

```
payload.<i>.metadata is invalid. Check it against the metadata JSON schema. Details: <detail>. <detail>. …
```

Common `<detail>` strings:

| Detail                                                                 | Cause                                                                                                         | Fix                                                        |
| ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `should have required property '<prop>'`                               | A required field is missing (`$schema`, `name`, `title`, `thumbnailURL`, `image`, `medium`, `yearOfCreation`) | Add the field                                              |
| `should NOT have additional properties ({"additionalProperty":"<x>"})` | A field not allowed by the schema version was sent (`additionalProperties: false`)                            | Remove `<x>`, or use a schema version that defines it      |
| `must be equal to one of the allowed values`                           | An `enum` value (e.g. `size.unit`, `edition.proofType`) is invalid                                            | Use an allowed value                                       |
| `$schema path is invalid, file is not found`                           | `$schema` points at an unknown schema version                                                                 | Use a valid `$schema` URL                                  |
| `$schemaIntegrity does not match $schema digest`                       | `$schemaIntegrity` hash is wrong                                                                              | Remove it (not required in v2.2) or set the correct digest |
| `royalty rate is out of the acceptable range of 0 to 100`              | `contractTerms.royaltyRate` out of range                                                                      | Use 0–100                                                  |

{% hint style="warning" %}
**v2.2 gotcha:** `chipUIDs` and `startbahnCertICTagUIDs` are **mutually required** — supplying only one fails with `should have required property 'chipUIDs'` (or `startbahnCertICTagUIDs`). And if `isDigital: true`, `digitalComponents` becomes required.
{% endhint %}

## Asynchronous (post-acceptance) failures

A `201` response (`status: "waiting_for_mining"`) means the request was accepted, not that minting succeeded. Blockchain-send failures surface later via the [webhook](/issue-transfer-api/issue-and-transfer-srr-nft/webhook-setup.md). Underlying reasons you may see in support/logs:

| Reason                                                | Meaning                                                                      |
| ----------------------------------------------------- | ---------------------------------------------------------------------------- |
| `API account is out of funds`                         | The relayer account needs funding — the transaction is retried automatically |
| `nonce is out of sync`                                | Transient nonce issue — auto-resent                                          |
| `transaction underpriced` / `replacement underpriced` | Gas price too low — auto-resent                                              |
| `gas required exceeds allowance`                      | Transaction would exceed gas limits                                          |

Confirm final state via the [subgraph](/subgraph/subgraph.md) or the issue/transfer [webhook](/issue-transfer-api/issue-and-transfer-srr-nft/webhook-setup.md).

## How to decode an error — quick steps

1. **Check `statusCode`** → use the [overview table](#status-code-overview).
2. **Is `message` an object with `results[]`?** → it's a [per-SRR code](#per-srr-issuance-error-codes); the failing `externalId` is named.
3. **Is `message` a string/array?** → it's a [request-level error](#request-level-errors-400); fix and resubmit the whole batch.
4. **`STARTRAIL_ERROR:` prefix?** → a downstream issue; check for [NFC/quota](#nfc-tags-and-quota-errors) keywords, else retry.
5. **Got `201` but no SRR minted?** → watch the [webhook](/issue-transfer-api/issue-and-transfer-srr-nft/webhook-setup.md); see [async failures](#asynchronous-post-acceptance-failures).

## Quick reference (for tooling/LLMs)

| key                                                  | status | shape     | meaning                                                                  |
| ---------------------------------------------------- | ------ | --------- | ------------------------------------------------------------------------ |
| `Missing header`                                     | 401    | string    | auth header absent                                                       |
| `API Key is not valid for <addr>`                    | 401    | string    | key ≠ issuer                                                             |
| `DUPLICATE_METADATA`                                 | 400    | per-SRR   | metadata already issued for artist                                       |
| `DUPLICATE_CHIP`                                     | 400    | per-SRR   | chip UID already used                                                    |
| `INVALID_CHIP`                                       | 400    | per-SRR   | chip UID malformed                                                       |
| `DUPLICATE_EXTERNAL_ID`                              | 400    | per-SRR   | externalId reused                                                        |
| `UNKNOWN_ARTIST`                                     | 400    | per-SRR   | artistAddress not a LUW                                                  |
| `SRR_NOT_CREATED`                                    | 400    | per-SRR   | on-chain create failed                                                   |
| `… metadata is invalid …`                            | 400    | string\[] | JSON-schema failure                                                      |
| `Some of the metadata is not defined`                | 400    | string    | entry missing metadata                                                   |
| `Address not found: <addrs>`                         | 400    | string    | issuer/artist not a LUW                                                  |
| `Duplicate Request Error: …`                         | 400    | string    | requestId reused                                                         |
| `Request Content Error: …`                           | 400    | string    | identical payload in flight/done                                         |
| `Attachment hash not ready …`                        | 400    | string    | file hash still computing                                                |
| `… attachment files were not found …`                | 400    | string    | file not uploaded                                                        |
| `File URLs must be Startbahn storage URLs …`         | 400    | string    | external URL in thumbnailURL/image/contractTerms.fileURL/attachmentFiles |
| `Metadata file URLs … must be publicly accessible …` | 400    | string    | thumbnailURL/image/contractTerms.fileURL in the private bucket           |
| `Metadata file(s) not found in storage …`            | 400    | string    | metadata file URL never uploaded                                         |
| `Metadata file(s) not ready for IPFS publication …`  | 400    | string    | file CID still computing                                                 |
| `STARTRAIL_ERROR: Quota limit exceeded!`             | 500    | string    | SRR quota exhausted                                                      |
| `STARTRAIL_ERROR: LUW missing NFC tag!`              | 500    | string    | NFC-tag allowance exceeded                                               |
| `STARTRAIL_ERROR: <msg>`                             | 500    | string    | forwarded downstream failure                                             |
| `UNKNOWN_ERROR`                                      | 500    | string    | unclassified                                                             |
| `[{ index, filePath }]`                              | 404    | object\[] | files not in storage (`/fileMetadata`)                                   |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.startrail.io/issue-transfer-api/issue-and-transfer-srr-nft/errors.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
