Error Codes
Stable failure codes used by Runlane errors and persisted failure summaries.
ErrorCode is the stable failure vocabulary across RunlaneError, RunFailure, and OutboxFailureRecord. Public code should branch on code, not parse message.
Raw driver, provider, or business-domain failures can be attached as cause for server-side logs, or summarized in meta for operator views. They are not the public code namespace.
retryable is part of each error or persisted failure record; it is not derived from ErrorCode alone. RunlaneError defaults to non-retryable, the storage-conflict helper defaults to retryable, and adapters or runtime code set retryability from the specific boundary failure.
ErrorCode
| Code | Value | Typical trigger | First response |
|---|---|---|---|
AdapterContractViolation | adapter_contract_violation | Adapter or transport contract mismatch | Fix the adapter/caller boundary. |
CapabilityUnsupported | capability_unsupported | Lane lacks a requested guarantee | Use a capable lane or disable the feature. |
ConfigurationInvalid | configuration_invalid | Malformed runtime, task, CLI, adapter, or lane options | Fix input/config; retrying unchanged will not help. |
InternalError | internal_error | Unexpected uncategorized framework failure | Inspect cause; narrow the code in implementation when understood. |
InvariantViolation | invariant_violation | Durable state or projection is impossible | Treat as bug/corruption; inspect run history and storage. |
OperationCancelled | operation_cancelled | Cooperative abort before completion | Let provider/runtime retry only when the boundary requires it. |
RunNotFound | run_not_found | Command references a missing run | Check environment/run id or use explicit new work APIs. |
ScheduleNotFound | schedule_not_found | Command references a missing schedule-owned record | Check environment/schedule identity. |
StorageConflict | storage_conflict | Stale sequence, owner, lease, occurrence, or outbox claim | Use storageConflictKind to retry, ignore, or return the winner. |
StorageUnavailable | storage_unavailable | Storage backend outage or unknown commit state | Retry only when safe; log backend cause. |
TaskFailed | task_failed | User task threw an unstructured error | Persist generic failure; put safe domain detail in meta. |
TaskNotFound | task_not_found | Runtime lacks the run's registered task | Fix task catalog/deployment routing. |
TransportPublishFailed | transport_publish_failed | Provider rejected a wakeup publish | Inspect provider metadata; retry only if retryable. |
TransportUnavailable | transport_unavailable | Transport backend cannot complete operation | Let outbox/provider retry after infrastructure recovers. |
ValidationFailed | validation_failed | Payload, persisted data, cursor, filter, or domain precondition failed validation | Fix the invalid value or schema boundary. |
ErrorCode.AdapterContractViolation (adapter_contract_violation)
Triggered when a Runlane package receives an internally inconsistent command or an adapter returns data that violates its contract.
Common causes:
- storage returns a run, event, outbox, or schedule record whose shape does not match the contract
- transport returns publish outcomes that are missing, extra, malformed, or no longer aligned by index
- an SQS helper receives a provider record shape or wakeup body that cannot be treated as a Runlane delivery message
- core detects that an adapter accepted a command it should have rejected
Treat this as an implementation bug or integration bug. Fix the adapter, transport bridge, test fixture, or caller boundary. Do not mask it with default values.
ErrorCode.CapabilityUnsupported (capability_unsupported)
Triggered when public runtime code asks the lane for a guarantee the lane does not report.
Common causes:
- using singleton keys with storage that does not report
enforcesSingleton - using bounded queue capacity with storage that does not report
enforcesQueueConcurrency - calling operator reads or pruning against a lane that does not expose those capabilities
- materializing schedules against storage that cannot claim schedule occurrences
Select a lane with the required capability, change the feature configuration, or fail the application action before calling Runlane.
ErrorCode.ConfigurationInvalid (configuration_invalid)
Triggered when application-supplied configuration or public options are malformed.
Common causes:
- invalid task ids, queue names, worker ids, schedules, retry policy, release values, duration strings, or runtime options
- queue registry drift, missing default queues, duplicate queues, or queue definitions that do not match the runtime registry
- invalid CLI config modules, command flags, dates, cursors, or runtime loading options
- invalid Postgres connection/schema options, SQS queue bindings, FIFO options, or lane package options
- malformed delivery messages at the runtime boundary before a run is claimed
Fix the input or deployment configuration. Retrying the same command without changing input should produce the same error.
ErrorCode.InternalError (internal_error)
Triggered when Runlane cannot classify an unexpected framework, adapter, or CLI failure with a narrower code.
Common causes:
- an adapter maps an unknown backend error after it fails to match known storage or transport categories
- persisted backend rows fail an adapter-owned parse in a way that indicates a bug or incompatible migration
- CLI command execution fails with an untyped thrown value
Treat this as a bug or corrupted environment until proven otherwise. Preserve the cause in server logs and reduce it to a narrower code when the failure mode becomes understood.
ErrorCode.InvariantViolation (invariant_violation)
Triggered when durable state or reducer state violates a framework invariant.
Common causes:
- impossible run event sequences or lifecycle transitions
- materialized run projections that disagree with replayed events
- lease, cancellation, dispatch, schedule, or outbox state that cannot be reconciled
- adapter-owned state that violates its own contract after being read back
This is not normal user input failure. Stop treating the affected run as healthy, inspect storage history, and fix the adapter/runtime bug or data corruption.
ErrorCode.OperationCancelled (operation_cancelled)
Triggered when work is intentionally aborted before Runlane can finish the operation.
Common causes:
executeDelivery(message, { signal })receives an already-aborted signal before the run is claimed- task code observes cancellation and throws a structured Runlane cancellation error
- a worker or process shutdown path aborts cooperative task execution
This is not a provider outage. For delivered transport messages, the operation rejects before acknowledgement so the provider can retry or redrive according to its policy. For task attempts, core maps the persisted task-facing message to Task was cancelled.
ErrorCode.RunNotFound (run_not_found)
Triggered when a command requires a specific run but storage cannot find it.
Common causes:
- an operator read, CLI command, cancellation, rerun, retry, or lease-owned operation references a run id outside the runtime environment
- the run was pruned or never existed
- a test or adapter command used the wrong environment/run id pair
Check the runtime environment and run id. Do not create a replacement run silently; use rerun() or trigger() explicitly when new work is desired.
ErrorCode.ScheduleNotFound (schedule_not_found)
Defined for commands that require a schedule occurrence or schedule-owned record that does not exist.
Common causes:
- a command references a missing schedule occurrence
- schedule storage state was pruned, migrated incorrectly, or queried under the wrong environment
Current first-party runtime paths usually report schedule materialization races through StorageConflict or bad schedule definitions through ConfigurationInvalid. If this code appears, treat it like a missing durable schedule record and inspect environment/schedule identity.
ErrorCode.StorageConflict (storage_conflict)
Triggered when storage rejects a stale owner, stale sequence, or competing claim.
Common causes:
- another caller appended to the run before this command's
expectedSequence - another trigger owns the idempotency key or singleton key
- another worker owns or won the run lease
- another scheduler owns the schedule occurrence
- another publisher owns the outbox claim
This code is often expected under concurrency. Inspect meta.storageConflictKind with getStorageConflictKind(error) to decide whether to retry, read the winning owner, ignore a lost race, or surface a real conflict to the caller.
ErrorCode.StorageUnavailable (storage_unavailable)
Triggered when the storage backend is reachable through the adapter contract but cannot complete the operation.
Common causes:
- Postgres connection failure, startup refusal, timeout, or transient backend outage
- database failover or pool exhaustion
- storage SDK or driver failure before Runlane can know whether a write committed
Treat this as retryable only when the error reports retryable: true or the surrounding operation is idempotent. Keep the raw driver failure in server logs through cause.
ErrorCode.TaskFailed (task_failed)
Triggered when user task code fails without throwing a structured RunlaneError.
Common causes:
- the task handler throws an ordinary
Error - the handler rejects with an unstructured value
- application code catches a provider failure and rethrows a generic error
Core persists a generic task-facing message, Task failed., so raw provider or secret-bearing text does not leak into run history. Put safe business/provider detail in failure meta when the task needs operator-visible context.
ErrorCode.TaskNotFound (task_not_found)
Triggered when a runtime tries to execute, rerun, retry, or inspect work for a task that is not registered in that runtime.
Common causes:
- a worker deployment is missing a task from
createRunlane({ tasks }) - a queue routes runs to a runtime that does not own that task catalog
- an operator rerun/manual retry references a source run whose task is no longer registered
Fix task registration or deployment routing. For delivered wakeups, core records a non-retryable failed run outcome so a poison provider message does not redeliver forever.
ErrorCode.TransportPublishFailed (transport_publish_failed)
Triggered when a transport provider rejects a wakeup publish attempt but the transport backend is still reachable enough to report the failure.
Common causes:
- AWS SQS returns failed
SendMessageBatchentries - provider validation rejects message size, FIFO dedupe/group options, queue permissions, or queue state
- a transport response is operation-level failed but not a connectivity outage
Provider request ids, response codes, sender-fault flags, and queue detail belong in meta. Retry only when the error or outbox failure is retryable; fix configuration/IAM/FIFO/provider policy for permanent provider rejections.
ErrorCode.TransportUnavailable (transport_unavailable)
Triggered when the transport backend cannot complete the operation or cannot produce trustworthy per-message publish outcomes.
Common causes:
- SQS SDK/network failure before publish outcomes exist
- long-running consumer receive/delete calls fail at the provider boundary
- local/test transport deliberately simulates transport outage
Treat this as infrastructure failure. Triggered runs remain durable; outbox recovery through tick() can retry publish after the configured retry delay.
ErrorCode.ValidationFailed (validation_failed)
Triggered when public data reaches the right boundary but fails validation.
Common causes:
- trigger payload validation fails before a run is created
- persisted payload revalidation fails before handler execution after schema drift
- storage query filters, pagination cursors, prune cursors, or date bounds are malformed at the adapter boundary
- operator commands fail domain preconditions, such as rerunning a non-terminal source run or manually retrying a non-failed source run
- adapter command or record data fails a public query/result schema that represents caller input rather than adapter internals
Fix the payload, cursor, filter, or schema boundary. Do not turn this into a generic task failure unless the validation failure happened inside user-owned task code.
StorageConflictKind
Storage adapters must create stale-owner conflicts with createStorageConflictError({ kind: StorageConflictKind.* }). That helper stores the stable kind in meta.storageConflictKind and defaults the error to retryable. Do not construct bare RunlaneError values with ErrorCode.StorageConflict for these cases.
| Enum | Value | Use |
|---|---|---|
StorageConflictKind.EventSequence | event_sequence | The caller's expected run event sequence no longer owns the projection. |
StorageConflictKind.IdempotencyKey | idempotency_key | A task-scoped idempotency key is still owned by another active or retained run. |
StorageConflictKind.LeaseOwnership | lease_ownership | A lease heartbeat, release, or outcome no longer owns the run lease. |
StorageConflictKind.OutboxClaim | outbox_claim | A publisher update no longer owns the claimed outbox row. |
StorageConflictKind.ScheduleOccurrence | schedule_occurrence | A schedule occurrence claim or completion no longer owns the occurrence. |
StorageConflictKind.SingletonKey | singleton_key | An environment-scoped singleton key is still owned by another active run. |
Persisted Failures
RunFailure.code is always an ErrorCode. Unknown handler exceptions become ErrorCode.TaskFailed; structured RunlaneError failures preserve their code while core maps the message to task-facing text.
Use RunFailure.meta for user or provider detail that Runlane does not own as lifecycle vocabulary.
Keep metadata small, JSON-safe, and non-secret. Prefer flat diagnostic values such as provider codes, request ids, or resource ids. Do not persist raw provider responses, credentials, tokens, large payloads, or personally sensitive data in run history.
For example, a payment task can persist { providerCode: 'payment_declined' } while keeping code: ErrorCode.TaskFailed; dashboards can group task failures by Runlane code and still show provider-specific detail.
OutboxFailureRecord.code is also an ErrorCode. Transport adapters should put provider response codes, request ids, and diagnostic detail in meta instead of creating a second code namespace.