Skip to content

Failure Model

OriginTS defines seven failure kinds. Failures are structured data, not exceptions. Execution aborts on the first failure, but lineage is preserved.

KindDescription
missingRequired data was not found
typeData did not match expected type
formatParsing or format error
constraintBusiness rule violation (e.g., from guard())
runtimeContext capability not available (e.g., readFile not provided)
panicUser-defined failure via panic() in match defaults
validationSchema validation failure

The result of run() is a discriminated union — never a thrown exception:

const result = await run(plan)
if (result.ok) {
console.log(result.value)
} else {
for (const failure of result.failures) {
console.error(`[${failure.kind}] ${failure.message}`)
// failure.nodeId maps back to the plan AST
}
}
  • Fail-fast — the first failure aborts execution. No partial results.
  • No silent coercions — types are checked exactly. A string "42" is not a number.
  • No exceptions escaperun() never throws for data errors. All failures are captured in the result.
  • Lineage is always available — even when execution fails, you get the lineage up to that point.

guard() produces constraint failures when a predicate returns false:

import { guard, tryExtract, literal } from '@origints/core'
// Fails with 'constraint' if age is negative
guard($.get('age').number(), v => (v as number) >= 0, 'Age must be non-negative')
// Combine with tryExtract for fallback
tryExtract(
guard($.get('age').number(), v => (v as number) >= 0, 'Age must be non-negative'),
literal(0)
)

PanicSpec signals that a code path should never be reached. Used as the default branch in MatchSpec:

import { panic } from '@origints/core'
// In a match expression default branch
panic('Unexpected document type')