# `ProblemCode`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `configurator-runtime.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Type · `import type { ProblemCode } from '@holostep-configurators/runtime-client/contract';` · stable · since 2.0.0 · section 2. Operations, reports, causes, problems

Open set: handle codes you don't know. Each code has a docs page ([`Problem.docs`](Problem.docs.md)) with its fix.
Problems are data: they never throw, on the strict fake too, which fails no test by itself: a
test asserts on `problems()` (empty, or exactly the codes it expects).
Codes are kebab-case, except the two that start with the member they report on, spelled as
that member is: 'beforeCommit-threw' and 'beforeCommit-slow' (not 'before-commit-…'). Compare
against this union, never a guessed spelling.

## Problem codes

| Code | Summary |
| --- | --- |
| [`'target-unmatched'`](../problems/target-unmatched.md) | A query matched nothing, or a placed model's `globalMaterialList` `meshName` matches none of its meshes but is close to one (a typo; once, at the commit that places the model); `didYouMean` names close authored names. |
| [`'target-ambiguous'`](../problems/target-ambiguous.md) | A single-part member (`follow` target, `attachTo`) matched several parts; nothing applied. |
| [`'asset-failed'`](../problems/asset-failed.md) | A GLB, texture or HDR failed in a declarative write; the write committed without it. |
| [`'asset-degraded'`](../problems/asset-degraded.md) | A preferred asset failed to fetch, decrypt or parse and a fallback was drawn instead: a `.holo`'s plain twin (`url` the `.holo`, spec section 8.5), or `glbUrl` after `optGlbUrl` failed (`url` the `optGlbUrl`, spec section 6.4). |
| [`'ready-timeout'`](../problems/ready-timeout.md) | Readiness expired: the commit shows with stand-ins or old looks until assets decode. |
| [`'transaction-timeout'`](../problems/transaction-timeout.md) | A transaction made no progress for `timeoutMs`, or hit the hold cap; it rolled back. |
| [`'write-after-close'`](../problems/write-after-close.md) | A write through a closed `tx` or its handles (HoloTransactionClosedError). |
| [`'beforeCommit-threw'`](../problems/beforeCommit-threw.md) | A [`beforeCommit`](Session.beforeCommit.md) function threw, or was pending after 10 s; its writes were undone. |
| [`'beforeCommit-slow'`](../problems/beforeCommit-slow.md) | A [`beforeCommit`](Session.beforeCommit.md) function averaged over about 5 ms across its last 10 commits; recorded at most once per function per 10 s, with the count and the mean in `message`. |
| [`'connection-stale'`](../problems/connection-stale.md) | A connection's planes no longer meet (0.5 mm, 0.5°); it was dropped. `message` has the gap. |
| [`'handle-disposed'`](../problems/handle-disposed.md) | A disposed handle or removed part was used; nothing happened. |
| [`'owner-disposed'`](../problems/owner-disposed.md) | Undo or redo skipped a change made by an owner that is disposed: listed in that undo's or redo's `problems`, `path` the owner's address (`/look/collections/{name}` for a collection). |
| [`'unsupported-spec'`](../problems/unsupported-spec.md) | A value this runtime or device can't apply (a UV channel, `sizeM` without `uvMetres`, a shading node, a linked light past the limit, a material `ref` no [`apply()`](Writer.apply.md) defines), or an unknown spec field from a page whose declared `contract` is newer than this runtime's (spec section 3.4); it was ignored. Also `CameraLimits.gestures: 'cooperative'` under an ancestor of `el` whose `touch-action` excludes `pan-y`: its touch half can't apply there (`path` '/camera/limits/gestures'). |
| [`'not-storable'`](../problems/not-storable.md) | Reserved: a value the stored format can't hold is an [`Issue`](Issue.md) of [`validate`](validate.md) and an `unstorable` entry of [`materialNodeFromSpec`](materialNodeFromSpec.md) ([`IssueCode`](IssueCode.md) 'not-storable'), never a Problem in 2.0.0; a branch on it as a Problem never runs. |
| [`'space-not-storable'`](../problems/space-not-storable.md) | Reserved: `space: 'parent'` in a document meant to be saved is an [`Issue`](Issue.md) of [`validate('configurator')`](validate.md) ([`IssueCode`](IssueCode.md) 'space-not-storable'), never a Problem in 2.0.0. |
| [`'frame-needs-compile'`](../problems/frame-needs-compile.md) | A [`Frame.material`](Frame.material.md) value needs a new shader; it was skipped. Recorded at most once per hook, material and field per 10 s, with the count in `message`. |
| [`'frame-budget'`](../problems/frame-budget.md) | Frame hooks together averaged over 3 ms per frame across the last 60 drawn frames, or a `constrain` over 1 ms across its last 60 calls; recorded at most once per 10 s for each, with the count and the mean in `message`. |
| [`'handler-threw'`](../problems/handler-threw.md) | An event handler or frame hook threw (a hook that throws 3 frames in a row is removed: 'hook-removed'). |
| [`'hook-removed'`](../problems/hook-removed.md) | A frame hook threw on 3 frames in a row and the runtime removed it: recorded once, right after that third 'handler-threw', with `path` 'onFrame' and the function's `name`, when it has one, in `message`; never again for that hook. Its disposer then does nothing; call [`onFrame`](Session.onFrame.md) again to run it. |
| [`'handler-async'`](../problems/handler-async.md) | An event handler returned a Promise (an untyped call); it was not awaited. |
| [`'handler-rejected'`](../problems/handler-rejected.md) | A Promise an event handler returned rejected. |
| [`'engine-conflict'`](../problems/engine-conflict.md) | Another 3D engine instance on the page conflicts with the runtime's (`info().renderer.engineConflict`). |
| [`'tenant-document-absent'`](../problems/tenant-document-absent.md) | No stored viewer-document layer for `configuratorId` (a 404; `info().document.layers` 'tenant'): the layers below apply. Never the scene model's source. |
| [`'tenant-document-unavailable'`](../problems/tenant-document-unavailable.md) | The stored viewer-document layer couldn't be fetched (any failure but a 404); the session runs with the layers below. |
| [`'defaults-unavailable'`](../problems/defaults-unavailable.md) | The platform or account defaults couldn't be fetched; built-in defaults apply. |
| [`'document-error'`](../problems/document-error.md) | A document layer has an invalid or version-1 key; `didYouMean` names its 2.0 home. |
| [`'apply-failed'`](../problems/apply-failed.md) | The runtime failed while applying a document layer, not for a bad key ('document-error'): one entry with `layer` and no `path` in [`ApplyReport.problems`](ApplyReport.problems.md) ([`applyDocument`](Session.applyDocument.md), `'document:applied'`); at boot, in [`info().problems`](InfoReport.problems.md). |
| [`'sync-failed'`](../problems/sync-failed.md) | An internal failure while the runtime applied a state write, recorded or look-only ([`setSceneModel`](Writer.setSceneModel.md), `undo`, [`Collection.set`](Collection.set.md), [`stage.set`](Stage.set.md), `attach`, a rule), through `session` or a `tx`, before its commit point: it, or the transaction holding it, rolled back with reason 'internal-error'; or while it applied a commit the runtime makes itself (a `commit: 'runtime'` drag's, a 'restore'), which rolls back, carries that commit's `op` (a drag's also its unit's `node`, the `op` its 'drag:end' carried) and releases a held drop pose; or when a member's on-demand code failed to load, for a write or a synchronous call that waited for it (spec section 6.3). |
| [`'host-disconnected'`](../problems/host-disconnected.md) | `el` left the document after [`boot`](boot.md), which freed the renderer for good (spec section 6.5). Recorded once, at the first later call other than [`destroy()`](Session.destroy.md) and the terminal calls, so an unmount that removes the DOM and then destroys records nothing. Pending and later Promise-returning calls reject AbortError; boot `el` again for a new session. |
| [`'render-lost'`](../problems/render-lost.md) | The view stopped drawing: the graphics context was lost and came back neither on its own nor on a fresh canvas. The stage stays blank until the page reloads; offer a reload. |
| [`'host-unsized'`](../problems/host-unsized.md) | `el` has no size to draw at: under 64 CSS px on a side, or not rendered (display: none on it or an ancestor), at the first drawn frame or a resize; once until it has a size again. A `div` with no CSS height is not unsized: it takes the view's default 2:1 shape ([`BootOptions.el`](BootOptions.el.md)). Give `el` a CSS size for the shape you want, and show it. |
| [`'unknown-boot-option'`](../problems/unknown-boot-option.md) | [`boot`](boot.md) got an option this contract doesn't have; it was ignored. |
| [`'unknown-event'`](../problems/unknown-event.md) | [`on()`](Session.on.md) got an event name that doesn't exist; it subscribed to nothing. |
| [`'invalid-input'`](../problems/invalid-input.md) | A call rejected or threw HoloInputError; recorded so an unawaited one is never silent. |
| [`'hotspot-id-taken'`](../problems/hotspot-id-taken.md) | Two hotspot badges share an `id`; the later one is skipped. |
| [`'deprecated'`](../problems/deprecated.md) | Reserved for a labs member or value that will change; the strict fake throws on it. No 2.0.0 member is deprecated, so no 2.0.0 call records it. |
| [`'not-permitted'`](../problems/not-permitted.md) | A gated capability this account may not use ([`permits()`](Session.permits.md) is false). |
| [`'unknown-capability'`](../problems/unknown-capability.md) | [`supports()`](Session.supports.md) got an id not in this runtime's [`KnownCapability`](KnownCapability.md), once per id per session; `didYouMean` names a 1.4 id's 2.0 id (none when the member is always present), else close known ids. |
| [`'connections-outdated'`](../problems/connections-outdated.md) | Stored connections whose [`connectionsBasis`](connectionsBasis.md) no longer matches their nodes: none restored. |
| [`'read-while-queued'`](../problems/read-while-queued.md) | Strict fake only: code read a target that still had a write queued behind a transaction. |

The set is open: a code newer than your declared contract arrives as `'other'`.

## Declaration

```ts
export type ProblemCode = 'target-unmatched' | 'target-ambiguous' | 'asset-failed' | 'asset-degraded' | 'ready-timeout' | 'transaction-timeout' | 'write-after-close' | 'beforeCommit-threw' | 'beforeCommit-slow' | 'connection-stale' | 'handle-disposed' | 'owner-disposed' | 'unsupported-spec' | 'not-storable' | 'space-not-storable' | 'frame-needs-compile' | 'frame-budget' | 'handler-threw' | 'hook-removed' | 'handler-async' | 'handler-rejected' | 'engine-conflict' | 'tenant-document-absent' | 'tenant-document-unavailable' | 'defaults-unavailable' | 'document-error' | 'apply-failed' | 'sync-failed' | 'host-disconnected' | 'render-lost' | 'host-unsized' | 'unknown-boot-option' | 'unknown-event' | 'invalid-input' | 'hotspot-id-taken' | 'deprecated' | 'not-permitted' | 'unknown-capability' | 'connections-outdated' | 'read-while-queued' | 'other';
```

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `ProblemCode` names no product |
| 2. A precedent | pass: [HTMLCanvasElement webglcontextlost](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/webglcontextlost_event) (row `G51`) |
| 3. Two apps, or labs | pass: 3 apps (ledger: app-4762caacdc, app-e3b47169bc, app-f9a32142f1) |
| 4. The cheaper fix first | decided per need in Appendix B: rows `G51` at tier stable (a member only where no rule, data, asset or app code serves the need) |
