Error reference

How Cruft reports failure: the message prefixes it writes to stderr, the exit codes it returns, the JavaScript and host error classes it throws, and the diagnostics specific to Cruft such as capability denials, TypeScript refusals, and compartment timeouts, so you can recognize and branch on each one.

How Cruft reports failure: message formats, error classes, exit codes, and the diagnostics unique to Cruft (capability denials, TypeScript refusals, compartment interrupts). Formats shown are from the shipping binary.

Message prefixes

Everything Cruft itself emits to stderr is prefixed and classifiable at a glance:

PrefixMeaning
cruft: evaluation error: <Name>: <msg>Uncaught JavaScript exception (raw value for non-Error throws)
cruft: evaluation error: CompileError("compile: parse: … @byte<N> @url=<url>")Syntax error (with byte offset and source URL)
cruft: syntax error in <file>: …--check mode failure
cruft: ts strip error in <path>: ts-strip @<off>: <reason>TypeScript refusal (see below)
cruft: bad option: <flag>Unrecognized CLI flag
cruft install: <ResolverError>Package resolution failure
cruft warn: …Non-fatal warning (e.g. legacy-peer-deps picks)

Exit codes

Cruft's own failures use sysexits.h classes (node uses 1 for most). The table from the CLI reference, by class:

CodeClassProduced by
0successclean run
Nprogram choiceprocess.exit(N), propagated faithfully
64EX_USAGEbad/unknown CLI flag
65EX_DATAERR--check syntax failure; TS strip refusal
66EX_NOINPUTentry file not found
1node-faithfuluncaught exception; syntax error at run time; unhandled rejection
70EX_SOFTWAREinstall resolution failure

Branch on non-zero-ness where portability matters; the specific codes are a tracked convention that may converge toward node's.

JavaScript error classes

The spec set (Error, TypeError, RangeError, ReferenceError, SyntaxError, URIError, EvalError, AggregateError, SuppressedError) behaves per ECMA-262, stacks, cause, subclassing. DOMException covers web-platform error names (e.g. AbortError).

Host error decoration: filesystem and other host operations throw real Errors decorated Node-style, .code (ENOENT, …), .errno, .syscall, .path, so ecosystem catch (e) { if (e.code === "ENOENT") … } patterns work unchanged.

error.stack frames name the source URL: files as file:///… URLs, inline evals as [eval], REPL lines as [repl:N]. Each frame carries an exact line:column, and frames elided by tail-call optimization are reconstructed. For silent bugs that never reach a throw, see Semantic debugging.

Capability denials (sealed/audit modes)

A denied operation throws a TypeError that names the capability, the operation, the denied module, and the mode, plus a grant hint:

TypeError: stdio.write(stdout): no stdio capability granted to module
'file:///app.mjs' (mode: sealed) — hint: add to cruft-caps.json:
{ "stdio": { "stdout": true } }
TypeError: process.spawn(echo): no process capability granted to module
'…' (mode: sealed) — hint: add to cruft-caps.json: { "exec": ["echo"] }

These are ordinary catchable TypeErrors: a program can feature-detect a sealed environment and degrade gracefully. The grant surface named by the hint is the cruft-caps.json file (see the CLI reference); add the capability the message names there, including the stdio family when a sealed program needs to print.

Compartment terminations

A compartment's timeout_ms expiry terminates evaluation from beneath the language. From the host side (your code that called evaluate) it surfaces as a catchable evaluation error ("Compartment evaluate exceeded its N ms timeout"); from inside the compartment it is not catchable, tenant try/catch cannot intercept it. That asymmetry is the security property.

TypeScript refusals

The type-eraser refuses constructs that require generating runtime code, with the reason inline:

cruft: ts strip error in <path>: ts-strip @0: TypeScript enum is not
supported: a runtime enum requires lowering to a runtime object, which the
type-eraser does not emit

Refused: enum, value namespace, constructor parameter properties. Everything type-only erases and runs (see TypeScript support). Exit code 65.

Unhandled rejections

An unhandled promise rejection is reported and fails the process (exit 1), stricter than older node defaults, aligned with modern node. process.on("unhandledRejection", handler) intercepts it.

Stub and partial-surface errors

By design, an unimplemented method on a present module throws explicitly at the method boundary rather than no-oping, so a missing feature fails loudly instead of returning a silent wrong result. This is a young surface: if you ever do hit a silently wrong result rather than a clear throw, treat it as a bug worth reporting rather than something to code around.

REPL rendering

The REPL re-renders errors as Uncaught <Name>: <message> on stdout, with internal decorations (byte offsets, URL tags) stripped; the session continues. See the REPL reference.

Install-time errors

cruft install prints resolver failures to stderr and exits 70. The notable case is a genuine peer conflict:

cruft install: Resolver(PeerConflict { name: "react", ranges: [...] })

which matches npm's ERESOLVE posture, resolve the conflict or opt into CRUFT_PM_LEGACY_PEER_DEPS=1 (which downgrades it to a cruft warn: line).