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

# Errors

Every error response uses the same shape:

```json theme={"dark"}
{
  "msg": "supplier product requires a supplier plant",
  "err_code": "err_supplier_product_missing_supplier_plant"
}
```

* **`err_code`** is a **stable, machine-readable** string. **Branch on this**, never on `msg`.
* **`msg`** is a human-readable explanation for logs and operators. Its wording may change at any time — do not parse it.

<Note>
  The code set may grow over time. Treat any `err_code` your integration does not recognize as **non-retryable** and surface it to an operator, rather than assuming success or blindly retrying.
</Note>

## Where `err_code` appears

Three places carry an `err_code`, and they are **not one shared vocabulary**:

| Field                      | Namespace                                                                                                                              | Meaning                                                                                                       |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `Error.err_code`           | `err_*`                                                                                                                                | The request failed. The catalog below is authoritative.                                                       |
| `LcaRecomputeJob.err_code` | `err_*` — same catalog                                                                                                                 | The request succeeded, but the background recompute it started later failed.                                  |
| `LcaBlocker.err_code`      | separate: `missing_input`, `mass_balance`, `electricity_guarantees_of_origin_mismatch`, `epd_not_usable`, `production_output_mismatch` | Nothing failed. A production year cannot be computed until you supply or correct the modelling data it names. |

A blocker is not an error: it is expected output of a healthy `200`. Match blocker
codes against their own set — an `err_*` code will never appear there, and a
blocker code will never appear in an error body.

## HTTP status

| Status | Meaning                                                                                                                              |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `400`  | The request could not be understood at the HTTP level — a malformed body or header, before any endpoint logic ran.                   |
| `401`  | No credentials, or the key is malformed, unknown, revoked, or expired.                                                               |
| `403`  | A valid key lacked the required permission, or targeted a resource outside its access.                                               |
| `404`  | The addressed entity does not exist.                                                                                                 |
| `405`  | The path exists but does not accept this HTTP method.                                                                                |
| `409`  | The request conflicts with current state (e.g. deleting an entity still in use, or an `external_id` already held by another entity). |
| `422`  | The request failed validation — its body, or a query parameter such as `cursor`.                                                     |
| `500`  | An unexpected server error occurred — surface it to an operator.                                                                     |
| `502`  | A transient upstream dependency failed — safe to retry with backoff.                                                                 |
| `503`  | The request was understood but could not be carried out right now — nothing changed, retry with backoff.                             |

Each operation's OpenAPI responses are authoritative for which of these statuses it can return.

## Error code catalog

The codes reachable from the API endpoints, with the recommended client action. This is the current known set; unknown codes should default to **surface to operator**.

| `err_code`                                    | HTTP          | When it happens                                                                                                                                                                                                                                                                                                                  | Client action                                              |
| --------------------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `err_not_authenticated`                       | 401           | No credentials, or a malformed / unknown / revoked / expired key (uniform — the failing check is not revealed)                                                                                                                                                                                                                   | Check the API key; not retryable as-is                     |
| `err_permission_denied`                       | 403           | Key lacks permission or is out of scope                                                                                                                                                                                                                                                                                          | Surface to operator                                        |
| `err_not_found`                               | 404           | The entity addressed by the request path does not exist. A reference in a request body that does not resolve is a `422` instead                                                                                                                                                                                                  | Fix the id, resend                                         |
| `err_composite_name_exists`                   | 409           | Another active composite at the same plant already has this name                                                                                                                                                                                                                                                                 | Choose another name, resend                                |
| `err_composite_used_in_supplier_products`     | 409           | The composite is still in use                                                                                                                                                                                                                                                                                                    | Remove references first                                    |
| `err_external_id_exists`                      | 409           | The code is already held by another active entity of the same type — on create or on update                                                                                                                                                                                                                                      | Choose another code, resend                                |
| `err_prechain_product_exists`                 | 409           | That product instance is already registered as a prechain product at that plant                                                                                                                                                                                                                                                  | Reuse the existing prechain product                        |
| `err_prechain_product_in_recipe`              | 409           | The prechain product is referenced by the BOM of an active product instance                                                                                                                                                                                                                                                      | Remove those BOM entries first                             |
| `err_product_instance_in_recipe`              | 409           | The instance is consumed by another active product's BOM                                                                                                                                                                                                                                                                         | Remove those BOM entries first                             |
| `err_silo_in_use`                             | 409           | The silo is referenced by the BOM of an active product                                                                                                                                                                                                                                                                           | Remove those BOM entries first                             |
| `err_silo_name_exists`                        | 409           | Another active silo or supplier product at the same plant already has this name                                                                                                                                                                                                                                                  | Choose another name, resend                                |
| `err_supplier_in_use`                         | 409           | The supplier company still has active supplier plants                                                                                                                                                                                                                                                                            | Delete those supplier plants first                         |
| `err_supplier_name_exists`                    | 409           | Another active supplier company at the same plant already has this name                                                                                                                                                                                                                                                          | Choose another name, resend                                |
| `err_supplier_plant_in_use`                   | 409           | Active supplier products are still sourced from the supplier plant                                                                                                                                                                                                                                                               | Delete those supplier products first                       |
| `err_supplier_plant_name_exists`              | 409           | Another active plant of the same supplier company already has this name                                                                                                                                                                                                                                                          | Choose another name, resend                                |
| `err_supplier_product_in_recipe`              | 409           | The supplier product is referenced by a BOM                                                                                                                                                                                                                                                                                      | Remove references first                                    |
| `err_supplier_product_in_silo`                | 409           | The supplier product is part of an active silo                                                                                                                                                                                                                                                                                   | Remove it from the silo first                              |
| `err_composite_not_allowed_in_recipe`         | 422           | The composite material type is not allowed in this product's BOM                                                                                                                                                                                                                                                                 | Remove the component, resend                               |
| `err_elementary_deactivated`                  | 422           | The `elementary_id` is no longer active                                                                                                                                                                                                                                                                                          | Choose another material type; operator                     |
| `err_elementary_not_allowed_in_recipe`        | 422           | The component's material type is not an ingredient of this product type                                                                                                                                                                                                                                                          | Remove the component, resend                               |
| `err_elementary_unknown_matching`             | 422           | The `elementary_id` is not recognized                                                                                                                                                                                                                                                                                            | Fix the middleware mapping; operator                       |
| `err_epd_unusable`                            | 422           | The linked EPD cannot be used                                                                                                                                                                                                                                                                                                    | Fix `epd_id`, or surface to operator                       |
| `err_invalid_moisture_content_range`          | 422           | `moisture_content_percentage` out of range                                                                                                                                                                                                                                                                                       | Fix input, resend                                          |
| `err_invalid_secondary_percentage_range`      | 422           | `secondary_percentage` out of range                                                                                                                                                                                                                                                                                              | Fix input, resend                                          |
| `err_invalid_lifetime_years`                  | 422           | `lifetime_years` is not greater than zero                                                                                                                                                                                                                                                                                        | Fix input, resend                                          |
| `err_material_no_limited_lifetime`            | 422           | `lifetime_years` is set for a material that cannot have a limited lifetime                                                                                                                                                                                                                                                       | Remove `lifetime_years`, resend                            |
| `err_lca_allocation_data_incomplete`          | 422           | Economic allocation applies to the production process, but a product it produces lacks its economic value or its production output for the year                                                                                                                                                                                  | Complete the data on every instance of the process, resend |
| `err_lca_production_output_mismatch`          | 422           | Economic allocation applies, but the production outputs of the process's products differ from the process's production output by more than 1 %                                                                                                                                                                                   | Correct the outputs or the process total, resend           |
| `err_material_not_hazardous`                  | 422           | Hazardous data set on a non-hazardous material                                                                                                                                                                                                                                                                                   | Fix input, resend                                          |
| `err_material_process_incompatible`           | 422           | The production process does not cover this product's material type                                                                                                                                                                                                                                                               | Choose another `production_process_id`, resend             |
| `err_moisture_content_not_bio_based`          | 422           | Moisture content set on a non-bio-based material                                                                                                                                                                                                                                                                                 | Fix input, resend                                          |
| `err_not_valid`                               | 400, 405, 422 | Generic request validation failure, including a malformed `cursor`, an out-of-range `limit`, or a request-body reference that does not resolve to one of your entities. Also carried by a `400` (unparseable request) and a `405` (wrong method for the path) — branch on the status to tell a fixable payload from a wrong call | Fix input, resend                                          |
| `err_prechain_circular_reference`             | 422           | The BOM would make the instance consume itself, directly or through another instance                                                                                                                                                                                                                                             | Fix the BOM, resend                                        |
| `err_process_plant_mismatch`                  | 422           | The production process belongs to a different plant than the instance                                                                                                                                                                                                                                                            | Choose another `production_process_id`, resend             |
| `err_product_category_not_allowed_at_plant`   | 422           | The plant does not produce this material type's category                                                                                                                                                                                                                                                                         | Choose another plant; operator                             |
| `err_product_mass_larger_than_recipe_mass`    | 422           | Product mass exceeds the sum of the mass all items in the BOM                                                                                                                                                                                                                                                                    | Fix the BOM, resend                                        |
| `err_product_mass_not_set`                    | 422           | The product's mass is unknown, so its BOM cannot be checked                                                                                                                                                                                                                                                                      | Set the mass-bearing `tech_specs`, resend                  |
| `err_product_missing_gwp_total`               | 422           | LCA cannot complete — a contributor is missing GWP                                                                                                                                                                                                                                                                               | Surface to operator (data completeness)                    |
| `err_product_missing_supplier`                | 422           | The product is missing a required supplier                                                                                                                                                                                                                                                                                       | Fix input, resend                                          |
| `err_product_type_no_recipe`                  | 422           | This product type is modelled without a BOM                                                                                                                                                                                                                                                                                      | Send an empty `bom`, resend                                |
| `err_secondary_percentage_not_customizable`   | 422           | Secondary content not customizable for this material                                                                                                                                                                                                                                                                             | Fix input, resend                                          |
| `err_supplier_product_missing_supplier_plant` | 422           | A supplier product needs a supplier plant                                                                                                                                                                                                                                                                                        | Fix input, resend                                          |
| `err_unit_not_allowed_for_material`           | 422           | The declared `unit` is not one this material type can be declared in                                                                                                                                                                                                                                                             | Choose an allowed unit, resend                             |
| `err_not_defined`                             | 500           | An unexpected server error occurred                                                                                                                                                                                                                                                                                              | Surface to operator                                        |
| `err_epd_service`                             | 502           | The upstream EPD service is unavailable                                                                                                                                                                                                                                                                                          | Retry with backoff                                         |
| `err_lca_update_not_queued`                   | 503           | The LCA recompute could not be queued; nothing was scheduled                                                                                                                                                                                                                                                                     | Retry with backoff                                         |
