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

# Errors

> Decode the Nomos error envelope and handle each error code.

Every error response uses the same JSON envelope, with a status code that follows standard HTTP semantics.

```json theme={null}
{
  "code": "BAD_REQUEST",
  "message": "invalid_type in 'customer.email': Required",
  "requestId": "37a04f8f-e791-491c-81e1-86cd304649bb",
  "docs": "https://docs.nomos.energy/api-references/errors/BAD_REQUEST"
}
```

| Field       | Description                                                                                                           |
| ----------- | --------------------------------------------------------------------------------------------------------------------- |
| `code`      | Machine-readable error code. Switch on this in your handler.                                                          |
| `message`   | Human-readable description of what went wrong.                                                                        |
| `requestId` | Unique request identifier. Include it when contacting support.                                                        |
| `docs`      | Link to the reference page for this code.                                                                             |
| `errors`    | Optional. Per-field breakdown of a validation or business-rule failure (see [Structured errors](#structured-errors)). |

<Tip>
  Always log the `requestId` alongside the request that caused the error. It's
  the fastest way for support to find the corresponding trace.
</Tip>

## Structured errors

When a request fails validation or a business rule, the envelope carries an additional `errors` array with a per-field breakdown. Switch on each entry's `code` to map the failure back to a specific input, instead of parsing the human-readable `message`.

<Note>
  The `errors` array is available from version `2026-05-27.curie` onwards. On
  earlier versions the envelope omits it and only `code`, `message`,
  `requestId`, and `docs` are returned.
</Note>

```json theme={null}
{
  "code": "BAD_REQUEST",
  "message": "We don't currently serve this postal code.",
  "requestId": "37a04f8f-e791-491c-81e1-86cd304649bb",
  "docs": "https://docs.nomos.energy/api-references/errors/BAD_REQUEST",
  "errors": [
    {
      "code": "unserviceable_zip",
      "field": "address.zip",
      "message": "We don't currently serve this postal code."
    }
  ]
}
```

Each entry has these fields:

| Field     | Description                                                                                                                                                           |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `code`    | Machine-readable reason for this field. Either a standard validation code (`invalid_type`, `too_small`, ...) or a Nomos-specific business code (`unserviceable_zip`). |
| `field`   | Dot-path to the offending field (`address.zip`). Empty for a top-level issue.                                                                                         |
| `message` | Human-readable description of this specific issue.                                                                                                                    |

The top-level `code` stays the coarse HTTP class (for example `BAD_REQUEST`); the `errors[].code` values are the granular reasons you switch on.

### Validation codes

These cover schema validation failures and map to the underlying validator's issue codes.

| Code                | Description                                                                         |
| ------------------- | ----------------------------------------------------------------------------------- |
| `invalid_type`      | Wrong type for the field, or the field is missing entirely.                         |
| `too_big`           | Value exceeds its maximum (number too large, string or array too long).             |
| `too_small`         | Value is below its minimum (number too small, string or array too short).           |
| `invalid_format`    | String doesn't match the expected format (email, UUID, ISO date, ...).              |
| `not_multiple_of`   | Number isn't a multiple of the required step.                                       |
| `unrecognized_keys` | The object contains keys that aren't allowed.                                       |
| `invalid_union`     | Not surfaced directly in `errors[]`; unions are flattened into their branch issues. |
| `invalid_key`       | A key in a record or map is invalid.                                                |
| `invalid_element`   | An element of a set or map is invalid.                                              |
| `invalid_value`     | Value isn't one of the allowed options (enum or literal mismatch).                  |
| `custom`            | A custom validation rule failed with no more specific code.                         |

### Business error codes

Beyond the validation codes above, `errors[].code` can carry a Nomos-specific business code:

| Code                          | Description                                                                                                                           |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `unserviceable_zip`           | The postal code in `address.zip` is outside the area Nomos serves.                                                                    |
| `unsupported_product`         | A requested entry in `product_orders` isn't offered by the subscription's plan.                                                       |
| `duplicate_customer_email`    | A customer with this email already exists under a different type, name, or company. Reconcile before retrying.                        |
| `invalid_iban`                | The IBAN in `payment_method.sepa_debit.iban` failed checksum validation.                                                              |
| `unsupported_meter`           | The plan doesn't support the capacity (RLM) meter named in `meter.type`.                                                              |
| `unsupported_meter_order`     | The subscription's plan offers no smart meter product, so a meter order can't be placed.                                              |
| `duplicate_meter_order`       | An active meter order of this product already exists for the subscription.                                                            |
| `ended_subscription`          | The subscription has ended, so a grid fee reduction can't be created for it.                                                          |
| `duplicate_grid_reduction`    | An active §14a EnWG grid fee reduction already exists for this module on the subscription.                                            |
| `missing_smart_meter`         | §14a EnWG module 3 requires a smart meter, which the subscription doesn't have.                                                       |
| `missing_module_1`            | §14a EnWG module 3 can only be ordered together with module 1.                                                                        |
| `out_of_period_meter_reading` | The reading `timestamp` falls on or after the subscription's end date.                                                                |
| `unsupported_meter_reading`   | Meter readings can only be reported for analog meters; this subscription's meter is smart.                                            |
| `upgrade_api_version`         | The request targets a feature (such as feed-in subscriptions) not available on the requested API version. Upgrade to a newer version. |

## Retrying

Retry only when retrying could plausibly succeed. Use exponential backoff with jitter and cap the attempts.

| Status                  | Retry                                |
| ----------------------- | ------------------------------------ |
| `4xx` (except `429`)    | No. Fix the request before retrying. |
| `429 TOO_MANY_REQUESTS` | Yes, after backing off.              |
| `5xx`                   | Yes, with exponential backoff.       |

## Error reference

| Status | Code                    | Description                                                                                                                                            |
| ------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `400`  | `BAD_REQUEST`           | Schema validation failed: missing fields, wrong types, or unparseable JSON. Check `message` and `errors[]` for the field path.                         |
| `401`  | `UNAUTHORIZED`          | No credentials, or the access token is invalid or expired. Refresh and retry. See [Authentication](/api-references/authentication).                    |
| `403`  | `FORBIDDEN`             | Valid token, but the caller doesn't have permission for this resource. Confirm the resource belongs to your organization and your Auth Client's scope. |
| `404`  | `NOT_FOUND`             | The resource doesn't exist, or your token can't see it. Double-check the ID and your organization.                                                     |
| `405`  | `METHOD_NOT_ALLOWED`    | The endpoint doesn't support the HTTP method you used.                                                                                                 |
| `409`  | `CONFLICT`              | Another resource already uses this value (for example, a globally unique email). Reuse it or change the value before retrying.                         |
| `422`  | `UNPROCESSABLE_ENTITY`  | Well-formed request that breaks a business rule (for example, cancelling an already-cancelled subscription). Read `message` for the specific rule.     |
| `429`  | `TOO_MANY_REQUESTS`     | Rate limit exceeded. Back off and retry with exponential delays.                                                                                       |
| `500`  | `INTERNAL_SERVER_ERROR` | Unexpected error on Nomos's side. Retry with backoff. If it persists, email [support@nomos.energy](mailto:support@nomos.energy) with the `requestId`.  |
