Skip to main content

ORK Errors Reference

ORK nodes report errors through a structured, stable error code taxonomy. Every error returned by an ORK either:

  • comes back as an RFC 9457 ProblemDetails response with a TIDE-ORK-* code in the code field and a matching URN in type, or
  • is wrapped in a legacy --FAILED-- envelope when the consumer is an older Tide component that cannot parse ProblemDetails

This page documents the format, the full code listing, the wire shapes, and how to add a new code without breaking cross-tier consumers.

Code format

TIDE-<PROJECT>-<CATEGORY>-<NAME>
  • <PROJECT> — always ORK for codes emitted by an ORK node
  • <CATEGORY> — a short uppercase category (VOUCHER, WALLET, AUTH, SIG, CRYPTO, HTTP, INTERNAL, LEGACY)
  • <NAME> — UPPER_SNAKE_CASE describing the specific condition

Examples:

TIDE-ORK-VOUCHER-VERIFY_FAILED
TIDE-ORK-AUTH-USER_NOT_FOUND
TIDE-ORK-CRYPTO-NULL_INPUT
TIDE-ORK-INTERNAL-UNEXPECTED

These strings are a stable contract. Other Tide repos (tide-js, idp-extensions, midgard) compare against these exact values to drive UI flows and downstream error reporting. Renaming a code requires coordinating across every consumer — treat them like a public API surface.

The constants live in Ork.Errors.TideErrorCodes in the ork repo and are the canonical source of truth.

Wire format — RFC 9457 ProblemDetails

When an ORK returns an error to a properly-modern caller (tide-js R3+, idp-extensions, anything emitting Accept: application/problem+json), the response body follows RFC 9457:

{
"type": "urn:tide:ork:VOUCHER-VERIFY_FAILED",
"title": "Voucher verification failed",
"status": 400,
"detail": "Voucher signature did not validate against the realm VRK",
"code": "TIDE-ORK-VOUCHER-VERIFY_FAILED",
"instance": "/Authentication/Voucher",
"traceId": "00-<32-hex>-<16-hex>-01"
}

Fields:

FieldTypeNotes
typeURIA URN of the form urn:tide:ork:<CATEGORY>-<NAME>. Stable; can be deep-linked from documentation
titlestringShort human-readable summary. Safe to render in a UI
statusintegerHTTP status code, typically 4xx for client errors and 5xx for server-side failures
detailstringLonger human-readable explanation. May reference specifics of the failure but must never contain user-identifying or cryptographic material
codestringThe full TIDE-ORK-* code. The primary key consumers should switch on
instancestringRequest path / context (often the route that produced the error)
traceIdstringW3C traceparent value, present when the ORK is in a traced flow

Content-Type is application/problem+json for RFC 9457 responses.

When writing a consumer, switch on code, not on status or titlestatus and title may evolve; code is the stable contract.

Legacy --FAILED-- envelope

For backward compatibility with older Tide nodes that cannot parse ProblemDetails, an ORK's outbound client (in Ork.Shared.Clients.ClientBase) recognises and surfaces the legacy --FAILED--[trace=...] envelope shape returned by older peers.

When ClientBase receives a legacy envelope from a peer, it:

  1. Logs a warning at WARN level identifying the response as legacy
  2. Constructs a ProblemDetails-shape result locally using the special code TIDE-ORK-LEGACY-FAILED_ENVELOPE
  3. Surfaces that to the caller, so callers always see a uniform shape

This means a caller that switches on code will see TIDE-ORK-LEGACY-FAILED_ENVELOPE for any legacy peer's failure response, regardless of what the peer would otherwise have wanted to report. Treat this code as "downstream node returned legacy failure envelope" — the actual cause is in the WARN-level log message body rather than the structured response.

When the entire fleet has rolled past the legacy version, the legacy-envelope code path in ClientBase can be deleted along with this section of the docs.

Code reference

Every code below is defined as a public const string in Ork.Errors.TideErrorCodes (in the ork repo). They are listed here grouped by category in the same order as they appear in the source — that order is the canonical reading order for adding new codes too.

Voucher / payment

CodeWhen emitted
TIDE-ORK-VOUCHER-VERIFY_FAILEDVoucher signature did not validate against the realm VRK
TIDE-ORK-VOUCHER-PAYMENT_REJECTEDPayer-side payment check failed (insufficient funds, expired subscription, etc.)
TIDE-ORK-VOUCHER-VRK_INVALIDVRK referenced by the voucher could not be resolved or has been revoked
TIDE-ORK-VOUCHER-ACTION_NOT_ALLOWEDThe voucher action is not permitted for this subscription tier
TIDE-ORK-VOUCHER-ACTION_UNKNOWNThe voucher action is not recognised in the closed action allow-list
TIDE-ORK-VOUCHER-SUBSCRIPTION_NOT_FOUNDNo active subscription was found for the request's customer / realm
TIDE-ORK-VOUCHER-SUBSCRIPTION_EXCEEDED_CONCURRENTSubscription's concurrent-action limit was exceeded
TIDE-ORK-VOUCHER-VENDOR_CREATION_NOT_ALLOWEDVendor creation is not permitted on this subscription
TIDE-ORK-VOUCHER-VENDOR_ALREADY_CREATEDA vendor with this identity already exists for this customer

Wallet lifecycle

CodeWhen emitted
TIDE-ORK-WALLET-PENDING_ALREADY_EXISTSA pending wallet for this UID already exists; the previous request did not complete or was abandoned

Authentication / authorization

CodeWhen emitted
TIDE-ORK-AUTH-NODE_NOT_AUTHENTICATORThe receiving ORK is not the configured authenticator for this UID and cannot proceed with the request
TIDE-ORK-AUTH-USER_NOT_FOUNDUID does not exist on this ORK's local authentication database
TIDE-ORK-AUTH-INVALID_AUTH_METHODThe requested authentication method is not configured on this node

Signing

CodeWhen emitted
TIDE-ORK-SIG-VERIFY_FAILEDCryptographic signature verification failed at a checkpoint in the signing protocol

Cryptography

CodeWhen emitted
TIDE-ORK-CRYPTO-NULL_INPUTA cryptographic primitive was invoked with a null required input (caller bug; should never occur at runtime)

HTTP / middleware

CodeWhen emitted
TIDE-ORK-HTTP-DECRYPTED_MISSINGRequest middleware expected a decrypted payload to be available downstream but none was present

Internal / catch-all

CodeWhen emitted
TIDE-ORK-INTERNAL-UNEXPECTEDCatch-all for any uncaught exception path. Should never appear in normal operation — its presence indicates an unhandled code path that needs investigation

Legacy compatibility

CodeWhen emitted
TIDE-ORK-LEGACY-FAILED_ENVELOPESynthesised by Ork.Shared.Clients.ClientBase when a downstream peer returns the pre-RFC9457 --FAILED--[trace=...] envelope. See Legacy --FAILED-- envelope for context

Trace propagation

Every ORK error response includes a traceId matching the W3C traceparent format. ORK adopts the inbound traceparent when called from a traced upstream (Phase 3 of the error-logging initiative), and propagates the same trace context on outbound calls via IHttpClientFactory + TidePropagationHandler.

In practice this means:

  • A single user-driven flow that crosses TideCloak → ORK → master → payer will share a traceId across every error or success response
  • Searching server logs for that traceId returns every span the flow touched
  • When debugging a multi-tier failure, start by extracting traceId from the failing user's response, then grep across all relevant ORK and TideCloak logs

If a request arrives without a traceparent, the ORK generates one and uses it for outbound propagation. Either way the client always sees a traceId in error responses.

Adding a new error code

Before adding a code, check that an existing code does not already cover the case. Code proliferation makes the consumer side harder to maintain.

When a new code is genuinely needed:

  1. Pick the category. If none of the existing categories fit, add a new category constant (still uppercase, still single-segment).
  2. Add the constant to Ork.Errors.TideErrorCodes in the canonical order (group with similar codes).
  3. Wire it at the emit site. Use the TideOperationException mechanism — bare throw new Exception is banned by BannedApiAnalyzers so the build will fail if you skip this step.
  4. Document it here. Add a row to the appropriate category table in this page describing when the code is emitted.
  5. Notify consumers. Open a tracking ticket for tide-js and any other repo that switches on TIDE-ORK-* codes — they may need to add a new branch in their error handler.
  6. Do not remove codes. Even if a code becomes unused on the emit side, removing it is a wire-breaking change for any consumer with stored data referencing it. Mark it deprecated in this doc instead.