Skip to documentation

SDK and error contracts

JavaScript API reference

JavaScript API reference Package @wisent/errors ( js/index.mjs , types in js/index.d.ts ); subpath @wisent/errors/codes ( js/codes.mjs , types in js/codes.d.ts ) exports the generated catalogue module alone. The main module re exports every

JavaScript API reference

Package @wisent/errors (js/index.mjs, types in js/index.d.ts); subpath @wisent/errors/codes (js/codes.mjs, types in js/codes.d.ts) exports the generated catalogue module alone. The main module re-exports everything from /codes, so one import serves both. Zero dependencies. All refusal sentences below are the exact strings thrown by the code.

Builders

failure({ failurePoint, code, service, impact, detail, cause, context }) → Envelope

Builds an envelope as a plain object with severity, retryable, outage filled from the catalogue. Throws TypeError on anything malformed:

condition exact sentence
failurePoint not a non-empty string failurePoint must be a non-empty string
failurePoint fails the grammar failurePoint <json> is not a dotted lowercase path
code not in the catalogue code <json> is not in the catalogue; one of config, auth, not_found, rate_limit, timeout, infra_down, unknown
service not a non-empty string service must be a non-empty string
detail provided but not a non-empty string detail must be a non-empty string

failurePoint and service are trimmed. impact is optional: any value is stringified and trimmed, empty becomes null. detail omitted or null serializes as null; provided, it is trimmed to DETAIL_LIMIT (2000). cause may be an envelope or a FailureError (unwrapped to its .envelope); context is shallow-copied and omitted when empty.

failureOrFallback(fields = {}) → Envelope

The same, but it never throws. Coercions, each recorded in context:

violation result context note
failurePoint absent/empty "unknown" wisent_errors.failure_point: "absent"
failurePoint malformed kept verbatim wisent_errors.failure_point: "malformed"
code absent "unknown" wisent_errors.error_code: "absent"
code off-catalogue "unknown" wisent_errors.error_code: "off-catalogue: <text>"
service absent/empty "unknown" wisent_errors.service: "absent"

Caller-provided context merges under the notes (notes win on collision).

raise(fields) → never

throw new FailureError(failure(fields)).

class FailureError extends Error

name is 'FailureError'; envelope carries the data; message is <failure_point>: <detail ?? operatorSummary(error_code)>.

Rendering

render(envelope) → string

One line: <operatorSummary> — <whose><retry> <JSON> where <whose> is our failure / the request or its credentials (from outage) and <retry> is ; retry later / ; retrying will not help (from retryable). The JSON is JSON.stringify(envelope).

chain(envelope) → string[]

One row per cause-chain layer, outermost first: <failure_point> [<error_code>] <detail ?? '-'>.

Trims

trimDetail(text, limit = DETAIL_LIMIT) → string

Stringifies (String(text ?? '')), strips whitespace at both ends, cuts hard at limit. The width is an argument because it is a product decision; the rule is the shared part.

trimDetailAtWordEdge(text, limit = DETAIL_LIMIT, slack = 24) → string

The same, cut back to the last space when one falls within slack characters of the bound; the result is right-trimmed. Opt-in, because it changes emitted bytes. The edge > 0 guard matters: lastIndexOf returns -1 when there is no space at all, and for any limit under slack a bare edge > limit - slack silently dropped the last character.

Catalogue module (@wisent/errors/codes)

Predicates and coercions

function returns
isCode(text) → boolean whether the catalogue knows this text; a type guard in TS; answered through a Set, so toString, __proto__ etc. are refused
codeOrNull(text) → Code | null the honest primitive at a wire boundary, where "nothing was declared" and "something unknown was declared" must stay apart
codeOrFallback(text) → Code the code, or FALLBACK ("unknown"); never throws

Derivations

function returns
severity(code) → 'warning' | 'error' | 'critical' from MEANINGS
retryable(code) → boolean from MEANINGS
outage(code) → boolean from MEANINGS
operatorSummary(code) → string the catalogue's per-code sentence
httpStatus(code) → number the edge status
exitCode(code, chosen) → number RETRY_EXIT (69) when retryable, else chosen
fromUpstreamStatus(status) → Code exact matches, then the inclusive 500–599 range → infra_down, else unknown

The derivation functions index MEANINGS[code] directly and are not guarded: handed an off-catalogue string they throw a bare TypeError (reading properties of undefined). Validate with isCode or coerce with codeOrFallback first at wire boundaries.

Constants

constant value
CODES frozen array of the seven codes, catalogue order
SEVERITIES frozen ["warning","error","critical"]
MEANINGS frozen per-code record: operatorSummary, retryable, outage, severity, httpStatus
FALLBACK "unknown"
FAILURE_POINT_PATTERN the grammar, as a string
RETRY_EXIT 69
DETAIL_LIMIT 2000 (main module only)

TypeScript

js/index.d.ts declares Code and Severity unions, Envelope, Context (Record<string, string | number | boolean | null>), strict Fields, and SalvageableFields (every field unknown, by design — "the fields the never-throwing builder accepts: anything"). isCode narrows to Code.