﻿# cyoda error reference

Every error response from the Cyoda REST API carries a structured `errorCode` in the `properties` object. Multiple codes may share the same HTTP status. P…

<em>cyoda-go version <a href="https://github.com/Cyoda/cyoda-go/releases/tag/v0.8.4">0.8.4</a></em>

# errors

## NAME

errors — error model and code catalogue.

## SYNOPSIS

REST responses use RFC 9457 Problem Details:

```json
{
  "type": "about:blank",
  "title": "Not Found",
  "status": 404,
  "detail": "ENTITY_NOT_FOUND: entity id=abc not found",
  "instance": "/api/v1/entities/abc",
  "properties": {
    "errorCode": "ENTITY_NOT_FOUND",
    "retryable": false
  }
}
```

gRPC error envelope example (returned in the CloudEvent response payload):

```json
{
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "entity id=abc not found",
    "retryable": false
  }
}
```

The gRPC response also carries `errorCode` and `retryable` in trailer metadata.

## DESCRIPTION

Every error response from the Cyoda REST API carries a structured `errorCode` in the `properties` object. Multiple codes may share the same HTTP status. Programmatic handling keys on `errorCode`, not HTTP status.

The `retryable` property is present and `true` only when the operation is safe to retry as-is (e.g., transient cluster conditions). When absent or `false`, the request or system state must change before retrying.

5xx responses include a `ticket` UUID for server-side log correlation. Share this value when reporting issues.

`CYODA_ERROR_RESPONSE_MODE` controls 5xx detail level. `sanitized` (default): generic message plus `ticket` UUID. `verbose`: internal error detail included in the response body; intended for development environments only.

## ERROR CODE INDEX

- `errors.BAD_REQUEST` — `400` — not retryable — request body, query parameter, or header is malformed or structurally invalid
- `errors.CLUSTER_NODE_NOT_REGISTERED` — `503` — retryable — target cluster node is not present in the gossip registry
- `errors.COMPUTE_MEMBER_DISCONNECTED` — `503` — retryable — compute member holding a processor assignment has disconnected
- `errors.CONFLICT` — `409` — retryable — generic 409 used by storage-level transaction serialization aborts (`RetryableConflict`); permanent business-logic conflicts use a specific code instead (e.g. `MODEL_ALREADY_LOCKED`, `ENTITY_MODIFIED`)
- `errors.DELETE_NOT_CONVERGED` — `409` — retryable — batched delete (`transactionSize`) kept finding newly created matching entities and was stopped at its batch cap; earlier batches stay deleted
- `errors.DISPATCH_FORWARD_FAILED` — `503` — retryable — HTTP forwarding call to peer node failed
- `errors.DISPATCH_TIMEOUT` — `503` — retryable (see note) — compute member did not respond within the dispatch timeout; completion on the remote node is not guaranteed
- `errors.DUPLICATE_AGGREGATION_ALIAS` — `400` — not retryable — two grouped-stats aggregations over different `(op, field)` pairs resolve to the same response key
- `errors.DUPLICATE_GROUP_BY` — `400` — not retryable — the same grouped-stats `groupBy` dimension was listed twice
- `errors.ENTITY_MODIFIED` — `412` — not retryable — `If-Match`-guarded entity update rejected; supplied transaction ID does not match the entity's current version
- `errors.ENTITY_NOT_FOUND` — `404` — not retryable — entity UUID does not exist or is not accessible to the caller
- `errors.EPOCH_MISMATCH` — `409` — retryable — writing node's cached shard epoch is stale; another node has since taken ownership
- `errors.FEATURE_DISABLED` — `404` — not retryable — Optional feature not enabled in this deployment.
- `errors.FORBIDDEN` — `403` — not retryable — authenticated caller lacks the required role or the tenant does not match
- `errors.GROUP_CARDINALITY_EXCEEDED` — `422` — not retryable — grouped-stats query produced more distinct buckets than `CYODA_STATS_GROUP_MAX` allows; no partial result is returned
- `errors.HELP_TOPIC_NOT_FOUND` — `404` — not retryable — help topic path does not resolve to any topic in the tree
- `errors.IDEMPOTENCY_CONFLICT` — `409` — not retryable — request with the same idempotency key was received but payload differs from the original
- `errors.INCOMPATIBLE_TYPE` — `400` — not retryable — entity payload's leaf value type is not assignable to the schema's declared DataType for that path; carries `fieldPath`, `expectedType`, `actualType` in `properties` (Cloud's `FoundIncompatibleTypeWithEntityModelException` equivalent)
- `errors.KEY_OWNED_BY_DIFFERENT_TENANT` — `409` — not retryable — Trusted-key registration collides with another tenant.
- `errors.KEYPAIR_NOT_FOUND` — `404` — not retryable — Referenced signing keypair does not exist.
- `errors.INVALID_CHANGE_LEVEL` — `400` — not retryable — `POST /model/{name}/{version}/changeLevel/{changeLevel}` supplied a value that is not one of `ARRAY_LENGTH`, `ARRAY_ELEMENTS`, `TYPE`, `STRUCTURAL`
- `errors.INVALID_AGGREGATION_FIELD` — `400` — not retryable — grouped-stats aggregation `field` is outside the scalar JSONPath grammar (most often a missing `$.` leader)
- `errors.INVALID_AGGREGATION_OP` — `400` — not retryable — grouped-stats aggregation `op` is not one of `sum`, `avg`, `min`, `max`, `stdev`
- `errors.INVALID_FIELD_PATH` — `400` — not retryable — search condition references one or more JSONPath field paths absent from the target model's locked schema; bounded refresh did not surface the path
- `errors.INVALID_GROUP_BY_PATH` — `400` — not retryable — grouped-stats `groupBy` entry is neither the reserved `state` token nor a JSONPath denoting a single scalar
- `errors.INVALID_LIMIT` — `400` — not retryable — grouped-stats `limit` is non-positive or greater than `CYODA_STATS_GROUP_MAX`
- `errors.MALFORMED_REQUEST` — `400` — not retryable — grouped-stats request body could not be read or decoded (invalid JSON, unknown top-level field, non-RFC 3339 `pointInTime`)
- `errors.MISSING_GROUP_BY` — `400` — not retryable — grouped-stats request omitted `groupBy` or sent it empty
- `errors.MODEL_ALREADY_LOCKED` — `409` — not retryable — admin operation requires `UNLOCKED` state but the model is `LOCKED` (relock attempt or re-import on a locked model)
- `errors.MODEL_ALREADY_UNLOCKED` — `409` — not retryable — admin operation requires `LOCKED` state but the model is `UNLOCKED` (unlock-of-already-unlocked-model)
- `errors.MODEL_HAS_ENTITIES` — `409` — not retryable — unlock or delete blocked because at least one entity of the model exists
- `errors.MODEL_NOT_FOUND` — `404` — not retryable — referenced entity model does not exist in the tenant's model registry
- `errors.MODEL_NOT_LOCKED` — `409` — not retryable — model exists but is not in `LOCKED` state; entity writes require a locked model
- `errors.NO_COMPUTE_MEMBER_FOR_TAG` — `503` — retryable — no live cluster node advertises the compute tag required by the processor
- `errors.NOT_FOUND` — `404` — not retryable — generic resource not found, used by admin endpoints (key pair lifecycle, trusted-key lifecycle); domain-specific resources have their own codes
- `errors.NOT_IMPLEMENTED` — `501` — not retryable — endpoint is defined but has no functional implementation in this version
- `errors.SEARCH_JOB_ALREADY_TERMINAL` — `400` — not retryable — operation attempted on a search job that has already completed, failed, or been cancelled
- `errors.SEARCH_JOB_NOT_FOUND` — `404` — not retryable — referenced search job does not exist in the current tenant
- `errors.SEARCH_QUEUE_FULL` — `503` — retryable — async-search worker pool has no free worker and its submit queue is at capacity
- `errors.SEARCH_RESULT_LIMIT` — `400` — not retryable — direct search's matched entity count exceeded the requested `limit` (a cap on the matched set, not a page size)
- `errors.SEARCH_SHARD_TIMEOUT` — `503` — retryable — one or more search shards did not respond within the configured timeout
- `errors.SEARCH_TIMEOUT` — `408` — retryable — client-requested search timeout expired before the result set was collected
- `errors.SERVER_ERROR` — `500` — retryable with caution — unclassified internal error; response includes `ticket` UUID for log correlation
- `errors.STORAGE_UNAVAILABLE` — `503` — retryable — storage layer could not supply a connection within its acquire deadline, or the transaction was reclaimed by the idle-in-transaction ceiling
- `errors.TRANSACTION_EXPIRED` — `400` — not retryable — transaction token's `exp` claim is in the past
- `errors.TRANSACTION_NODE_UNAVAILABLE` — `503` — retryable — cluster node that owns the open transaction is unreachable
- `errors.TRANSACTION_NOT_FOUND` — `404` — not retryable — transaction ID does not correspond to an active transaction on this node
- `errors.TRANSACTION_TIMEOUT` — `408` — retryable — client-requested transaction timeout expired before commit
- `errors.TRANSITION_NOT_FOUND` — `400` — not retryable — requested workflow transition is not defined for the entity's current state
- `errors.TRUSTED_KEY_CAP_REACHED` — `400` — not retryable — Per-tenant trusted-key cap reached.
- `errors.TRUSTED_KEY_NOT_FOUND` — `404` — not retryable — referenced trusted-key KID is not present in the registry (delete / invalidate / reactivate target missing)
- `errors.TX_CONFLICT` — `409` — retryable — transaction aborted due to storage-level serialization conflict
- `errors.TX_COORDINATOR_NOT_CONFIGURED` — `503` — not retryable — distributed transaction coordinator is disabled or misconfigured on this node
- `errors.TX_NO_STATE` — `404` — not retryable — coordinator has no state record for the given transaction ID
- `errors.TX_REQUIRED` — `400` — not retryable — operation requires a transaction context but none was provided
- `errors.UNAUTHORIZED` — `401` — not retryable — `Authorization` header is missing, token is expired, signature is invalid, or issuer is untrusted
- `errors.UNSUPPORTED_ALGORITHM` — `400` — not retryable — Requested JWT algorithm not supported in this version.
- `errors.UNSUPPORTED_KEY_TYPE` — `400` — not retryable — JWK `kty` not supported in this version.
- `errors.VALIDATION_FAILED` — `400` — not retryable — payload is structurally valid JSON but fails the model's schema or workflow validation rules
- `errors.WORKFLOW_FAILED` — `400` — not retryable — workflow processor or guard condition returned a failure during state transition
- `errors.WORKFLOW_NOT_FOUND` — `404` — not retryable — workflow definition referenced by the entity model does not exist

## SEE ALSO

- openapi
- grpc
- config

## Subtopics

- [`cyoda help errors BAD_REQUEST`](/help/errors/bad_request/) — Fired when the server cannot parse or structurally process the incoming request. Common triggers include invalid JSON, unsupported format specifiers, a parameter outside its allowed range, and mutually exclusive parameters set together.
- [`cyoda help errors CLUSTER_NODE_NOT_REGISTERED`](/help/errors/cluster_node_not_registered/) — The request was routed to or requires a specific cluster node that is not present in the registry. Occurs during startup, rolling restarts, or after a node failure before the gossip layer has converged.
- [`cyoda help errors COMPOSITE_KEY_UNSUPPORTED`](/help/errors/composite_key_unsupported/) — Composite unique key enforcement is an optional capability that storage backends may or may not implement. This error is returned when a model defines one or more unique keys but the backend does not implement the `CompositeUniqueKeyCapable` interface.
- [`cyoda help errors COMPUTE_MEMBER_DISCONNECTED`](/help/errors/compute_member_disconnected/) — The compute member responsible for executing a processor or workflow step disconnected before completing the operation. The task may or may not have been executed.
- [`cyoda help errors CONDITION_TYPE_MISMATCH`](/help/errors/condition_type_mismatch/) — Validation is parse-based: a comparison or range operand is rejected only when it parses into none of the field's declared DataTypes. For example `"abc"` against a DOUBLE field is rejected — it is not a number. A numeric-looking string against a polymorphic `[INTEGER, STRING]` field is accepted (it parses as STRING).
- [`cyoda help errors CONFLICT`](/help/errors/conflict/) — The server detected that the entity was modified by another writer between the time it was read and the time the current write was committed. Normal outcome under concurrent load.
- [`cyoda help errors DELETE_NOT_CONVERGED`](/help/errors/delete_not_converged/) — `DELETE /entity/{entityName}/{modelVersion}` with `transactionSize` set (and no `pointInTime`) deletes in batches, re-selecting the matching entities before each batch. It finishes when a selection pass finds nothing left. If entities matching the condition are created at least as fast as they are removed, that pass never comes up empty, so the delete is capped at a fixed number of batches and fails with this code instead of running indefinitely.
- [`cyoda help errors DISPATCH_FORWARD_FAILED`](/help/errors/dispatch_forward_failed/) — The cluster dispatcher attempted to forward a processor invocation or criteria evaluation to a peer node but the HTTP call to that peer failed (network error, peer crash, or connection refused). The operation has not been executed on the target node.
- [`cyoda help errors DISPATCH_TIMEOUT`](/help/errors/dispatch_timeout/) — A workflow processor, criteria evaluation, or function callout was dispatched to a compute member but the response did not arrive within the callout's own `responseTimeoutMs` (a field on the processor, criteria, or function config; default `30000` ms) — not any cluster forwarding timeout.
- [`cyoda help errors DUPLICATE_AGGREGATION_ALIAS`](/help/errors/duplicate_aggregation_alias/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query`. Each bucket's `aggregations` object is keyed by the aggregation's `as` alias, or — when `as` is omitted — by a synthesized `<op>_<field>` with the leading `$.` stripped, so `{"op":"sum","field":"$.amount"}` becomes `sum_amount`. Two aggregations that compute different things cannot share one key, because only one of the two values could be returned under it.
- [`cyoda help errors DUPLICATE_GROUP_BY`](/help/errors/duplicate_group_by/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query`. The reserved token `state` appearing twice, or the same JSONPath appearing twice, is rejected rather than deduplicated: a repeated dimension adds a second copy of the same value to every bucket's `groupKey` and changes nothing about the grouping, so it is more likely a mistake in the request than an intent.
- [`cyoda help errors ENTITY_MODIFIED`](/help/errors/entity_modified/) — When an entity update request carries an `If-Match` header, the server requires the supplied transaction ID to equal the entity's current `meta.transactionId`. A mismatch means another writer has updated the entity since the caller's last read. The optimistic-concurrency guard rejects the update rather than silently overwrite.
- [`cyoda help errors ENTITY_NOT_FOUND`](/help/errors/entity_not_found/) — No entity with the given ID exists in the tenant's data store, or the entity existed at a point-in-time that precedes the requested snapshot. Also returned for audit log lookups when the specified event or message cannot be found.
- [`cyoda help errors EPOCH_MISMATCH`](/help/errors/epoch_mismatch/) — Shard ownership is tracked by an epoch counter that increments whenever the cluster re-partitions. A write is rejected with this error when the writing node's cached epoch is stale — another node has since taken ownership of the shard. This prevents split-brain writes.
- [`cyoda help errors FEATURE_DISABLED`](/help/errors/feature_disabled/) — Returned by trusted-key endpoints when `CYODA_IAM_TRUSTED_KEY_REGISTRATION_ENABLED=false` (the default):
- [`cyoda help errors FORBIDDEN`](/help/errors/forbidden/) — The request was authenticated successfully but the caller's JWT claims do not include the role required by the endpoint (for example, `admin` is required for administrative operations). Tenant mismatch — where the caller's tenant does not match the resource — also produces this error.
- [`cyoda help errors GROUP_CARDINALITY_EXCEEDED`](/help/errors/group_cardinality_exceeded/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query`. `CYODA_STATS_GROUP_MAX` (default `10000`) bounds the number of distinct buckets the endpoint will build. The bound is enforced on both execution paths — the backend's native GROUP BY pushdown and the in-process streaming tally — so the same query is rejected identically on every storage backend.
- [`cyoda help errors HELP_TOPIC_NOT_FOUND`](/help/errors/help_topic_not_found/) — Returned by `GET {ContextPath}/help/{topic}` when `{topic}` is well-formed (matches `[A-Za-z0-9._-]+`) but does not resolve to any topic in the tree. Clients should `GET {ContextPath}/help` to discover available topic paths.
- [`cyoda help errors IDEMPOTENCY_CONFLICT`](/help/errors/idempotency_conflict/) — The idempotency key is supplied via the `Idempotency-Key` HTTP header on collection create and update requests. See `crud` for the request shape.
- [`cyoda help errors INCOMPATIBLE_TYPE`](/help/errors/incompatible_type/) — Returned by `POST /entity/{format}/{name}/{version}` and the entity-update surfaces when a leaf field's value cannot be coerced into the model's declared DataType (e.g. submitting `"abc"` against an `INTEGER` field, or `13.111` against an `INTEGER` field on a model whose `changeLevel` is empty so type widening is not in scope).
- [`cyoda help errors INVALID_AGGREGATION_FIELD`](/help/errors/invalid_aggregation_field/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query`. An aggregation `field` obeys exactly the grammar a `groupBy` path does — a required `$.` leader followed by dot-separated segments of ASCII letters, digits, `_` and `-`, with no bracket-quoted access, array subscript or projection, recursive descent, whitespace or non-ASCII character. See `cyoda help errors INVALID_GROUP_BY_PATH` for the grammar and the rejected spellings; the message names the offending field and the reason.
- [`cyoda help errors INVALID_AGGREGATION_OP`](/help/errors/invalid_aggregation_op/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query`. The supported operators are `sum`, `avg`, `min`, `max` and `stdev`, spelled lowercase. Anything else — including `count`, an uppercase spelling, or a typo — is rejected, and the message echoes the value that was sent.
- [`cyoda help errors INVALID_CHANGE_LEVEL`](/help/errors/invalid_change_level/) — The `changeLevel` path segment must be exactly one of: `ARRAY_LENGTH`, `ARRAY_ELEMENTS`, `TYPE`, or `STRUCTURAL`. Comparison is case-sensitive. Any other value (including the empty string, lower-cased variants, or typos) yields this error.
- [`cyoda help errors INVALID_CONDITION`](/help/errors/invalid_condition/) — Endpoints that accept a search-style condition in the request body — sync and async search, grouped statistics, and the conditional form of delete-by-model — reject a body whose condition cannot be parsed or is otherwise structurally invalid. The condition type is unrecognised, a nested clause is malformed, the JSON does not match the expected condition envelope, an `operatorType` is not one of the canonical operators, a `LIKE` or `MATCHES_PATTERN` operand is not a valid pattern, a `BETWEEN`/`BETWEEN_INCLUSIVE` operator's value is not a two-element array, a `group` clause's `operator` is not `AND`, `OR`, or `NOT`, or a `NOT` group's `conditions` does not hold exactly one entry (zero, or two or more).
- [`cyoda help errors INVALID_FIELD_PATH`](/help/errors/invalid_field_path/) — Three checks emit this code.
- [`cyoda help errors INVALID_GROUP_BY_PATH`](/help/errors/invalid_group_by_path/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query`. Every `groupBy` entry other than `state` must match the wire JSONPath grammar — a required `$.` leader followed by dot-separated segments of ASCII letters, digits, `_` and `-`:
- [`cyoda help errors INVALID_LIMIT`](/help/errors/invalid_limit/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query`. `limit` is optional; when present it is a top-N cap on the buckets returned, and it must be greater than zero and no greater than the server's `CYODA_STATS_GROUP_MAX` (default `10000`). A value outside that range is rejected up front rather than clamped, so the response never silently covers a smaller set than the one asked for. The message carries the configured maximum.
- [`cyoda help errors INVALID_UNIQUE_KEY`](/help/errors/invalid_unique_key/) — A composite unique key requires every declared field to be present and non-null. This error is returned when the entity payload is missing a value for at least one key field, or the value cannot be normalized to a valid claim (for example, a NaN or ±Infinity for a numeric key field).
- [`cyoda help errors INVALID_UNIQUE_KEY_DEFINITION`](/help/errors/invalid_unique_key_definition/) — Each unique key on a model must have a non-empty list of field paths, a unique name within the model, and field paths that resolve to existing, non-ambiguous fields in the model schema. This error is returned when a submitted model definition violates one of these structural requirements.
- [`cyoda help errors KEYPAIR_NOT_FOUND`](/help/errors/keypair_not_found/) — Returned by:
- [`cyoda help errors KEY_OWNED_BY_DIFFERENT_TENANT`](/help/errors/key_owned_by_different_tenant/) — Trusted keys are tenant-scoped. When `POST /oauth/keys/trusted` is called with a `keyId` that already belongs to a different tenant, the request is rejected with `409`. Pick a fresh `keyId` (the caller cannot see or affect the other tenant's keys).
- [`cyoda help errors M2M_CLIENT_NOT_FOUND`](/help/errors/m2m_client_not_found/) — Returned by `/clients` admin endpoints when the supplied `clientId` does not match any registered M2M client in the caller's tenant:
- [`cyoda help errors MALFORMED_REQUEST`](/help/errors/malformed_request/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query` when the body cannot be read from the connection, is not valid JSON, or does not decode into the request shape. Decoding is strict: an unrecognised top-level field is rejected rather than ignored, so a misspelled `agregations` fails here instead of quietly running with no aggregations. A `pointInTime` that is not RFC 3339 also lands here, because it is rejected while the body is being decoded — there is no separate code for it.
- [`cyoda help errors MISSING_GROUP_BY`](/help/errors/missing_group_by/) — Raised by `POST /api/entity/stats/{entityName}/{modelVersion}/query`. `groupBy` is required and must carry at least one dimension: the endpoint returns one bucket per distinct group key, and there is no reading of the request that groups by nothing.
- [`cyoda help errors MODEL_ALREADY_LOCKED`](/help/errors/model_already_locked/) — Returned by any admin operation that requires the model be in the `UNLOCKED` state, including:
- [`cyoda help errors MODEL_ALREADY_UNLOCKED`](/help/errors/model_already_unlocked/) — Returned when `POST /model/{name}/{version}/unlock` is issued against a model whose current state is `UNLOCKED`. Distinct from `MODEL_NOT_LOCKED`, which is reserved for the entity-write-without-lock path on the entity service: this code is the symmetric counterpart of `MODEL_ALREADY_LOCKED` for the admin lifecycle.
- [`cyoda help errors MODEL_HAS_ENTITIES`](/help/errors/model_has_entities/) — Both `POST /model/{name}/{version}/unlock` and `DELETE /model/{name}/{version}` require zero entities of the target model. The cardinality check guards against silent loss of data and against schema drift on a model whose lifecycle is presumed frozen.
- [`cyoda help errors MODEL_NOT_FOUND`](/help/errors/model_not_found/) — The entity type or model name specified in the request does not exist in the tenant's model registry. Occurs on write paths (creating entities with an unknown type, importing data that references a missing model, performing model lifecycle transitions on a model ID that does not exist) and on read paths (list, stats, grouped-stats, and search operations that reference an unregistered model).
- [`cyoda help errors MODEL_NOT_LOCKED`](/help/errors/model_not_locked/) — Entity creation and bulk write operations require the model to be in the `LOCKED` lifecycle state. Models in `DRAFT` or unlocked-for-editing state reject writes to prevent schema changes from affecting in-flight data.
- [`cyoda help errors NOT_FOUND`](/help/errors/not_found/) — Returned by administrative endpoints (key pair lifecycle, trusted-key lifecycle) when the supplied identifier does not match any registered resource. The submitted identifier is never echoed in the response body — only a generic descriptor — so attackers cannot use the response as a reflection oracle. The identifier is logged server-side at INFO for operator correlation.
- [`cyoda help errors NOT_IMPLEMENTED`](/help/errors/not_implemented/) — The route is defined and accepted by the server but the handler returns this error because the feature is pending implementation. Distinct from a `404` — the endpoint exists without a functional implementation.
- [`cyoda help errors NO_COMPUTE_MEMBER_FOR_TAG`](/help/errors/no_compute_member_for_tag/) — Workflow processors are dispatched to nodes that advertise matching compute tags. When no node with the required tag is alive in the cluster within the configured wait timeout (`CYODA_DISPATCH_WAIT_TIMEOUT`), the operation is rejected with this error.
- [`cyoda help errors OIDC_INVALID_TENANT`](/help/errors/oidc_invalid_tenant/) — cyoda treats legal entity identifiers as UUIDs. OIDC provider ownership is
recorded as a `uuid.UUID` `OwnerLegalEntityID` field, which keys both the
per-tenant KV blob storage and the validated user-context tenant binding at
token validation time.
- [`cyoda help errors OIDC_PROVIDER_DUPLICATE`](/help/errors/oidc_provider_duplicate/) — Each tenant may register a given `wellKnownConfigUri` only once. Submitting
`POST /oauth/oidc/providers` with a URI that is already registered for the
caller's tenant returns this error.
- [`cyoda help errors OIDC_PROVIDER_INACTIVE`](/help/errors/oidc_provider_inactive/) — `PATCH /oauth/oidc/providers/{id}` requires the provider to be in the active
state. If the provider has been invalidated via
`POST /oauth/oidc/providers/{id}/invalidate`, this error is returned.
- [`cyoda help errors OIDC_PROVIDER_NOT_FOUND`](/help/errors/oidc_provider_not_found/) — The provider UUID supplied in the path parameter does not correspond to a
registered OIDC provider for the caller's tenant. Either the provider was
never registered, was deleted, or the UUID belongs to a different tenant
(cross-tenant existence is not disclosed).
- [`cyoda help errors OIDC_SSRF_BLOCKED`](/help/errors/oidc_ssrf_blocked/) — When registering an OIDC provider, cyoda validates the `wellKnownConfigUri`
against a blocklist of private address ranges (loopback, RFC1918, link-local,
IPv6 ULA). If the URI's hostname resolves to any blocked range, the
registration is rejected to prevent Server-Side Request Forgery attacks.
- [`cyoda help errors PRECONDITION_REQUIRED`](/help/errors/precondition_required/) — PATCH applies a merge patch to the entity's stored state rather than replacing it wholesale. Because the patch is applied relative to the current stored data, cyoda-go requires the caller to state a precondition explicitly via `If-Match`. Omitting the header entirely is rejected.
- [`cyoda help errors SCHEDULE_FUNCTION_INVALID_RESULT`](/help/errors/schedule_function_invalid_result/) — A `TransitionSchedule.function` callout must return `resultKind: "Schedule"` with a value shaped `{fireAt|fireAfterMs, expireAt?|expireAfterMs?}` — exactly one of `fireAt`/`fireAfterMs`, and at most one of `expireAt`/`expireAfterMs`. This error is raised when the compute node returns a different `resultKind`, or a `Schedule` value that is malformed: missing or duplicate fire/expiry fields, an unknown field, or a non-numeric value.
- [`cyoda help errors SEARCH_JOB_ALREADY_TERMINAL`](/help/errors/search_job_already_terminal/) — Search jobs are long-running asynchronous operations. Once a job reaches a terminal state it cannot be cancelled, resumed, or otherwise modified. This error is returned when such an operation is attempted on a finished job — `PUT /search/async/{jobId}/cancel` is the only endpoint that raises it.
- [`cyoda help errors SEARCH_JOB_NOT_FOUND`](/help/errors/search_job_not_found/) — Polling a search job by ID returns this error when the job ID is unknown or belongs to a different tenant. Jobs are tenant-scoped; a valid job ID from one tenant is not visible to another.
- [`cyoda help errors SEARCH_QUEUE_FULL`](/help/errors/search_queue_full/) — `POST /api/search/async/{entityName}/{modelVersion}` runs on a bounded worker pool: a fixed number of workers drain a fixed-capacity queue. Submission fails fast with this error rather than blocking the request or spawning an unbounded goroutine per submission. The rejected submit leaves nothing behind — no job row, no id to poll.
- [`cyoda help errors SEARCH_RESULT_LIMIT`](/help/errors/search_result_limit/) — Direct (synchronous) search is bounded-or-fail: `limit` caps the matched result set rather than paging it. When more entities match than the limit allows, the request is rejected — it never returns a truncated prefix, because a partial result would be indistinguishable from a complete one.
- [`cyoda help errors SEARCH_SHARD_TIMEOUT`](/help/errors/search_shard_timeout/) — Distributed search fans out to multiple shards in parallel. If any shard does not return results before the search timeout expires, the job is marked failed and this error is returned. Occurs under high load, during partial cluster degradation, or with expensive queries.
- [`cyoda help errors SEARCH_TIMEOUT`](/help/errors/search_timeout/) — Fires when the client-supplied `timeoutMillis` elapses before the search result set was fully collected. No partial results are returned.
- [`cyoda help errors SERVER_ERROR`](/help/errors/server_error/) — The server encountered an unclassified internal error. The response body contains a `ticket` UUID that correlates with the server-side error log. No internal details are exposed in the response.
- [`cyoda help errors STORAGE_UNAVAILABLE`](/help/errors/storage_unavailable/) — Raised in three cases, all transient:
- [`cyoda help errors TRANSACTION_EXPIRED`](/help/errors/transaction_expired/) — Transaction tokens are short-lived bearer tokens issued when a transaction is opened. This error fires when the token's `exp` claim is in the past at the time the proxy validates it. The transaction itself may still be active server-side, but the token is no longer valid for routing.
- [`cyoda help errors TRANSACTION_NODE_UNAVAILABLE`](/help/errors/transaction_node_unavailable/) — Transaction state is pinned to the node that opened it. If that node crashes or becomes unreachable while the transaction is in progress, subsequent requests using the transaction token are rejected with this error because the proxy cannot forward them to the owner.
- [`cyoda help errors TRANSACTION_NOT_FOUND`](/help/errors/transaction_not_found/) — The transaction ID supplied in the request does not correspond to an active transaction. The transaction may have been committed, rolled back, expired, or may never have existed. Also occurs when a request is mis-routed to a node that never opened the transaction.
- [`cyoda help errors TRANSACTION_TIMEOUT`](/help/errors/transaction_timeout/) — Fires when the client-supplied `transactionTimeoutMillis` elapses before the first commit. Nothing was committed.
- [`cyoda help errors TRANSITION_NOT_FOUND`](/help/errors/transition_not_found/) — Entity workflow state machines define explicit transitions between states. This error fires when a transition is triggered that does not exist in the model's workflow definition for the entity's current state. Also occurs when the transition name is misspelled, when the transition is disabled, when it is a scheduled transition (those fire on their timer and are never manually fireable), or when the entity is in a terminal state that allows no further transitions.
- [`cyoda help errors TRUSTED_KEY_CAP_REACHED`](/help/errors/trusted_key_cap_reached/) — `POST /oauth/keys/trusted` enforces a per-tenant cap (default 10, configurable via `CYODA_IAM_TRUSTED_KEY_MAX_PER_TENANT`). The cap counts only currently-valid keys (Active and not past `validTo`). Delete or invalidate older keys, or raise the cap.
- [`cyoda help errors TRUSTED_KEY_NOT_FOUND`](/help/errors/trusted_key_not_found/) — Returned by trusted-key admin endpoints when the supplied KID does not match any registered key:
- [`cyoda help errors TX_CONFLICT`](/help/errors/tx_conflict/) — Reserved. Not currently emitted by any cyoda-go code path.
- [`cyoda help errors TX_COORDINATOR_NOT_CONFIGURED`](/help/errors/tx_coordinator_not_configured/) — Reserved. Not currently emitted by any cyoda-go code path.
- [`cyoda help errors TX_NO_STATE`](/help/errors/tx_no_state/) — Reserved. Not currently emitted by any cyoda-go code path.
- [`cyoda help errors TX_REQUIRED`](/help/errors/tx_required/) — Reserved. Not currently emitted by any cyoda-go code path.
- [`cyoda help errors UNAUTHORIZED`](/help/errors/unauthorized/) — Returned when the `Authorization` header is missing, the bearer token is expired, the token signature is invalid, or the token was issued by an untrusted issuer. Also returned when a request reaches a protected route with no identity context established by the auth middleware.
- [`cyoda help errors UNIQUE_VIOLATION`](/help/errors/unique_violation/) — The entity payload contains field values that collide with an existing entity's composite unique key. Unlike an optimistic-concurrency CONFLICT (which is retryable), a unique-key violation is a permanent data constraint — retrying the same payload without changing the key field values will produce the same result.
- [`cyoda help errors UNSUPPORTED_ALGORITHM`](/help/errors/unsupported_algorithm/) — cyoda-go v0.8.0 signs and verifies only `RS256`. Other enum values declared in the OpenAPI spec (`RS384`, `RS512`, `PS256`, `PS384`, `PS512`, `ES256`, `ES384`, `ES512`, `EdDSA`) are rejected with this error. Cyoda Cloud supports the full enum; parity is tracked in a v0.8.1 follow-up.
- [`cyoda help errors UNSUPPORTED_KEY_TYPE`](/help/errors/unsupported_key_type/) — `POST /oauth/keys/trusted` accepts only `kty: "RSA"` in v0.8.0. Cloud also supports `kty: "EC"` and `kty: "OKP"`; cyoda-go parity is tracked in a v0.8.1 follow-up.
- [`cyoda help errors UNSUPPORTED_MEDIA_TYPE`](/help/errors/unsupported_media_type/) — Returned by PATCH in two situations:
- [`cyoda help errors VALIDATION_FAILED`](/help/errors/validation_failed/) — Unlike `BAD_REQUEST` (which covers parse failures, bad parameters, and unstorable bytes), this error is returned when the payload parsed and then failed against the registered model. On an entity write that means:
- [`cyoda help errors WORKFLOW_FAILED`](/help/errors/workflow_failed/) — During an entity create or transition operation the associated workflow processors (pre-processors, post-processors) or guard conditions ran but one of them signalled failure. The failure message from the processor is included in the error detail.
- [`cyoda help errors WORKFLOW_NOT_FOUND`](/help/errors/workflow_not_found/) — Entity models reference a workflow by name to govern state transitions. This error is returned when the named workflow cannot be found in the tenant's workflow registry, during entity type registration or when a model references a workflow that was deleted.
- [`cyoda help errors WORKFLOW_SCHEMA_VERSION_UNSUPPORTED`](/help/errors/workflow_schema_version_unsupported/) — Every workflow definition must declare a schema version in `MAJOR.MINOR` format (for example `"version": "1.1"`). This error is returned when the import request contains a version string that does not match any supported schema version.

## See also

- [`cyoda help openapi`](/help/openapi/) — cyoda-go generates its OpenAPI 3.1 specification from the embedded `api/openapi.yaml` file compiled into the binary at build time. The spec is served at `/openapi.json` with runtime-patched server URLs. The Scalar API Reference UI is served at `/docs` and loads the spec from `/openapi.json`.
- [`cyoda help grpc`](/help/grpc/) — cyoda-go exposes one gRPC service: `CloudEventsService` (package `org.cyoda.cloud.api.grpc`). All gRPC methods use the CloudEvents Protobuf envelope (`io.cloudevents.v1.CloudEvent`) as both request and response types. The event type string in the CloudEvent envelope selects the operation; the JSON payload in `text_data` (or `binary_data`) carries the operation-specific body.
- [`cyoda help config`](/help/config/) — Environment variables beat default values. The `_FILE` suffix variant takes precedence over the plain variable when both are set — for example, `CYODA_POSTGRES_URL_FILE=/etc/secrets/db-url` wins over `CYODA_POSTGRES_URL`. There are no command-line flags for configuration values; env vars are the sole configuration surface.

## Raw formats

- [`/help/errors.json`](/help/errors.json) — full descriptor (matches `GET /help/{topic}` envelope)
- [`/help/errors.md`](/help/errors.md) — body only