{
"msg": "supplier product requires a supplier plant",
"err_code": "err_supplier_product_missing_supplier_plant"
}
err_codeis a stable, machine-readable string. Branch on this, never onmsg.msgis a human-readable explanation for logs and operators. Its wording may change at any time — do not parse it.
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.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. |
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. |
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_product_instance_has_declarations | 409 | The instance has a declaration in review or verified | Not deletable while that declaration stands |
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 of yours already has this name, ignoring case and surrounding whitespace | Choose another name, or reuse the existing supplier company |
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, ignoring case and surrounding whitespace. Plants of two different supplier companies may share a name | Choose another name, or reuse the existing supplier plant |
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 |