Reference: Runtime Error Registry
Last verified 2026-09-03 against engine v1.0.232.
The runtime error registry is the closed, typed taxonomy of runtime gateway failures: one catalog that every runtime failure resolves a stable machine code against, projected to the frontend and to a generated reference, and read at the boundary that turns a thrown error into a player-safe public code. This page is the contract for its surfaces, invariants, proof surfaces, and limits. It links down to the generated catalog and never restates it; for the codes themselves, their categories and dispositions, and the static copy each carries, read the generated reference.
ReferenceRuntime Error Catalog (generated)Resolved signature, schema and exampleThe model behind this reference (why failures are typed rather than parsed, and which behaviors are the catalog's versus the frontend's) is in the Runtime Error Registry explanation.
Source of truth
The taxonomy is owned in one file and projected, never re-authored:
- The catalog
RUNTIME_ERROR_CATALOGinserver/src/modules/runtime/errors/runtimeErrorCatalog.tsis the single source of truth. The code unionRuntimeGatewayErrorCode, the orderedRUNTIME_ERROR_CODES, the closedRUNTIME_ERROR_CATEGORIES, and the lookupruntimeErrorCatalogEntryall derive from it. - The frontend registry
web_client/spa/src/runtime/generated/runtimeErrorRegistry.gen.tsis generated from the catalog bygenerateRegistrySourceinscripts/generate-runtime-error-registry.mjs. - The generated reference
docs/spec/generated/error-catalog.mdis generated from the same catalog bygen-error-catalog-docs.ts. - The boundary classifier
runtimeGatewayPublicCodeinserver/src/modules/runtime/routes.tsmaps a thrown error to a stable public code, andruntimeGatewayPublicMessageForCodemaps that code to player copy from the catalog.
Surfaces
| Surface | Symbol |
|---|---|
| Catalog constant and derived code union | RUNTIME_ERROR_CATALOG, RUNTIME_ERROR_CODES, RuntimeGatewayErrorCode in server/src/modules/runtime/errors/runtimeErrorCatalog.ts |
| Entry shape | RuntimeErrorCatalogEntry in server/src/modules/runtime/errors/runtimeErrorCatalog.ts |
| Closed category tuple | RUNTIME_ERROR_CATEGORIES in server/src/modules/runtime/errors/runtimeErrorCatalog.ts |
| Engine-contract prefix family | RUNTIME_ENGINE_CONTRACT_CODE_PREFIX in server/src/modules/runtime/errors/runtimeErrorCatalog.ts |
| Lookups | runtimeErrorCatalogEntry, isRuntimeGatewayErrorCode, isRuntimeGatewayCodedError in server/src/modules/runtime/errors/runtimeErrorCatalog.ts |
| Total disposition | runtimeErrorCategoryDisposition, assertNever in server/src/modules/runtime/errors/runtimeErrorCatalog.ts |
| Throw facade | codedError, RuntimeGatewayCodedError in server/src/modules/runtime/errors/runtimeErrorCatalog.ts |
| Frontend registry generator | generateRegistrySource, writeRegistry, checkRegistryDrift, OUTPUT_PATH in scripts/generate-runtime-error-registry.mjs |
| Generated frontend registry | RUNTIME_ERROR_REGISTRY_GEN in web_client/spa/src/runtime/generated/runtimeErrorRegistry.gen.ts |
| Generated-reference generator | gen-error-catalog-docs.ts emitting docs/spec/generated/error-catalog.md |
| Boundary classifier and copy | runtimeGatewayPublicCode, runtimeGatewayPublicMessageForCode, runtimeGatewayPublicMessage in server/src/modules/runtime/routes.ts |
| Frontend presentation | feCategoryForCode, runtimeErrorPresentation in web_client/spa/src/runtime/runtimeErrorPresentation.ts |
Invariants
Each row is backed by a named conformance test or check.
| Invariant | Proven by |
|---|---|
| The committed frontend registry is a byte-exact projection of the catalog (a fresh render equals the committed file), and the generator's own drift check reports no drift. | server/tests/runtimeErrorTaxonomy.test.ts (FE registry codegen is in sync); check:runtime-error-registry |
| Every catalogued code and the engine-contract prefix are present in the rendered registry. | server/tests/runtimeErrorTaxonomy.test.ts (every catalogued code and the engine-contract prefix is present in the rendered registry) |
| No message-regex error classification survives under the runtime module. | check:runtime-error-taxonomy part (a), delegated to scripts/check-no-prose-error-matching.mjs |
Every codedError("literal") throw site names a catalog code (engine-contract prefix allowed); variable-argument sites are type-checked instead. | check:runtime-error-taxonomy part (c), analyzeCodedErrorSites in scripts/check-runtime-error-taxonomy.mjs |
The routes boundary is catalog-backed and the hand tables are deleted; player copy routes through runtimeErrorCatalogEntry. | server/tests/runtimeErrorTaxonomy.test.ts (the boundary is catalog-backed; the legacy public-message table and both hand-tables are deleted) |
| Every code the deleted public table used to ship still has a catalog entry. | server/tests/runtimeErrorTaxonomy.test.ts (catalogues every code the deleted public table used to ship) |
The classifier maps thrown errors to the correct public code: the two internal aliases resolve to game_full and game_updating, catalog members pass through, and an untyped error maps to runtime_internal. | server/src/modules/runtime/runtimeGatewayErrors.test.ts (runtimeGatewayPublicCode cases) |
Category and retryability rules hold (auth is terminal except runtime_credential_expired; schema_violation is never retryable; revoked is terminal and non-retryable; capacity is terminal-but-retryable; the first-frame family is retryable and non-terminal at the base). | server/tests/runtimeErrorTaxonomy.test.ts (category and retryability invariants) |
The category disposition is total at compile time (assertNever) and at runtime. | server/tests/runtimeErrorTaxonomy.test.ts (runtimeErrorCategoryDisposition is total over the closed category union) |
RuntimeGatewayCodedError populates code/category/retryable/terminal from the catalog, chains the cause, and is narrowable by code. | server/tests/runtimeErrorTaxonomy.test.ts (RuntimeGatewayCodedError throw contract) |
| The generated reference is a byte-exact render of the catalog. | gen-error-catalog-docs.ts --check, run inside gen-docs:check |
Proof surfaces
- Frontend drift-sync.
server/tests/runtimeErrorTaxonomy.test.tsrenders the catalog fresh and asserts byte-equality with the committedruntimeErrorRegistry.gen.ts;checkRegistryDriftin the generator pins the same equality as a check. - Boundary classification.
server/src/modules/runtime/runtimeGatewayErrors.test.tsdrivesruntimeGatewayPublicCodeandruntimeGatewayPublicMessageacross the alias, authority-recovering, access-denied, admission, and untyped cases, and asserts no internal prose reaches player copy. - Boundary lint.
check:runtime-error-taxonomy(in the rootcheckchain) delegates no-prose-classification toscripts/check-no-prose-error-matching.mjs, runs the generator drift check, and runsanalyzeCodedErrorSitesoverserver/src/modules/runtime;check:runtime-error-registry(also in the chain) runs the generator drift check on its own. - Generated-reference drift.
gen-error-catalog-docs.ts --checkinsidegen-docs:checkholdsdocs/spec/generated/error-catalog.mdbyte-exact against the catalog.
Numbers
The runtime error code count and category count are carried by the generated reference (its Error code count and Category count lines) and are not restated here; read them from the generated Runtime Error Catalog. They are pinned by gen-docs:check (byte-exact projection) and by the drift-sync and deleted-table-coverage tests in server/tests/runtimeErrorTaxonomy.test.ts.
| Value | Symbol | Receipt |
|---|---|---|
Engine-contract code prefix runtime_engine_contract_ | RUNTIME_ENGINE_CONTRACT_CODE_PREFIX in server/src/modules/runtime/errors/runtimeErrorCatalog.ts | server/tests/runtimeErrorTaxonomy.test.ts (the engine-contract prefix is present in the rendered registry); gen-error-catalog-docs.ts --check |
The retryable and terminal values are per-entry data, not numeric constants; they are pinned by the category and retryability invariants above rather than by a scalar.
Limits
- Terminal-when-disconnected is not catalog data. The first-frame family is retryable and non-terminal in the catalog; the disconnected-terminal promotion lives in
TERMINAL_WHEN_DISCONNECTEDinweb_client/spa/src/runtime/runtimeErrorPresentation.ts. - The Retry affordance is frontend policy.
NO_RETRY_ACTIONinruntimeErrorPresentation.tsdecides whether a Retry label appears; the catalog does not carry it. - Two internal codes are not catalog members.
RUNTIME_CAPACITY_EXHAUSTED_CODEandRUNTIME_DEPLOYMENT_SUPERSEDED_CODEinserver/src/modules/runtime/runtimeGatewayErrors.tsonly alias ontogame_fullandgame_updatinginsideruntimeGatewayPublicCode. runtime_origin_forbiddenbypasses the catalog. It is emitted directly as a 403 with an inline message inserver/src/modules/runtime/routes.ts, is not a catalog member, does not pass through the classifier orruntimeGatewayPublicMessageForCode, and returns nothing fromruntimeErrorPresentationon the frontend (generic fallback copy). The catalog is the taxonomy the classifier produces, not every code the gateway can emit.- The frontend category enum is hand-maintained.
feCategoryForCodeinruntimeErrorPresentation.tsis distinct from the taxonomy category and falls back to a generic connection category for any unmapped taxonomy value, so a newly added taxonomy category is not surfaced there automatically. runtime_connection_unverifiedis a retained catch-all kept for server-table coverage during migration; new throw sites should use a specific split code (runtime_auth_invalid,runtime_credential_expired,runtime_release_stale_link, orruntime_session_ended).- Variable-argument
codedError(code)sites are out of scope for the taxonomy gate and rely on the TypeScript union check instead ofanalyzeCodedErrorSites. - The
runtime_internaloperator description names a stale logger. The live logger islogRuntimeGatewayUntypedErrorinserver/src/modules/runtime/routes.ts; the operator string recorded on theruntime_internalentry names a different, non-live function and is emitted verbatim into the generated reference. It is operator-facing text only and never reaches a player. - The unit is not enrolled in the feature-contract registry.
server/src/lib/featureContractRegistry.tscarries no entry for it, so the closure gate does not yet force its anchor to resolve; it sits at the internal tier.