Skip to main content
InvariantCAD distinguishes expected modeling failures from programmer mistakes. Evaluation, parsing, topology, mass, and BOM operations commonly return CadResult; invalid direct authoring calls can throw TypeError or RangeError immediately.

Diagnostic shape

Branch on code, not message text. Messages are written for people and can be clarified without a protocol change. path uses document-oriented paths when a specific authored field is responsible. related identifies other document locations involved in the same failure, such as the other end of a conflicting reference.

Complete bounded-parse example

This canonical module configures a document-byte ceiling, deliberately exceeds it, and branches on the structured resource details instead of parsing the human-readable message.
The release gate compiles and executes the source module from examples/docs/diagnostics-and-resource-limits.ts.

Common code families

Authoring exceptions

These are programmer mistakes and throw immediately:
  • duplicate IDs
  • cross-design references
  • a face selection passed to a fillet
  • an empty Boolean tool array
  • a configuration with no overrides
  • non-positive tolerances
  • unsupported literal authoring option values
Catch them at application input boundaries if users directly drive a builder. Do not catch and ignore them inside a model definition. For the unreleased public imported-body workflow, invalid caller definitions and unsafe source descriptors return IMPORT_SOURCE_INVALID; invalid evaluation options return IR_INVALID. Resource failures identify the resolution, commitment, or resource-limit phase without exposing bytes. The resolver is not invoked when the selected kernel lacks the strong exact single-solid capability or the operation is already aborted.

Document preflight limits

Default validation bounds include: Parsing captures an untrusted JSON-shaped input into a bounded plain copy while reading each source property at most once. Cycles, sparse arrays, exotic prototypes, stateful accessors, and work beyond the configured bounds fail before schema traversal.

Why limits are part of correctness

A shape can be mathematically valid but operationally unsafe to materialize. InvariantCAD therefore also bounds topology snapshot normalization, persistent matching, exact native evolution reports, conformance witnesses, and artifact sizes. Raising a limit changes the accepted workload and should be reviewed like a resource-policy change.

Source-only staged external products

The repository-only product evaluator adds a document-scoped resource boundary for direct external-part occurrences and fixed external subassemblies. externalAssembly(resource, output) selects one assembly output from a committed InvariantCAD document and expands its child-local part and assembly tree. Each active occurrence path may cross at most one external-document boundary. This is source-only work staged for 0.2, not a public 0.1.1 evaluator, resolver, builder, or CLI API. Resolver requests made by this operation include a frozen documentScope. { source: "root" } identifies commitments in the product document. A child resource uses { source: "external", resource: <root resource ID>, digest: <root digest> }. The scope is part of resource identity: the same resourceId in two admitted child documents represents two distinct commitments. Repeating the same (documentScope, resourceId) reuses the verified bytes. Ordinary resolveResourcesV7(...) calls omit documentScope. The product uses one cumulative resource-resolution session across external document JSON and later child geometry: All selected external-document commitments are preflighted and resolved before child assembly expansion or part preparation. Each later resolution phase is also fully preflighted, including its effect on cumulative counts and committed bytes, before a resolver callback for that phase. A later phase that would exceed the shared budget therefore fails before any child geometry callback, even when external document JSON has already been resolved. Suppressed branches are pruned before descendant document admission and do not consume those descendant product-work ceilings. An occurrence-specific external child failure is reported at the parent occurrence’s component pointer. Structured details always add componentResource, the selected output/outputKind, and the full occurrencePath. After the child document is admitted, details also include its digest, byteLength, and admitted sourceVersion. If the child diagnostic already names its own resource, that value is preserved instead of being overwritten. A child-owned output is preserved separately as childOutput, while output continues to name the external component output selected by the parent. The original child location is preserved as childNode and childPath when supplied. A fixed-subassembly leaf also retains its child part node and the child assembly/component location when the failure belongs to that leaf. Internal selectors used to evaluate those leaves are never reported as authored output names. Deferred external BOM warnings keep the same component provenance, so applications can identify both the product occurrence and the child-document cause without parsing message text. An aggregate limit, preflight, or shared child-resource failure that cannot be attributed to one leaf remains at the selected external component boundary. A failure shared by several leaves of one fixed subassembly is not attached to an arbitrary first leaf merely to supply a child node or part name. An externalAssembly(...) declaration whose selected child output is not actually an assembly fails after committed child-document admission and before geometry work. A missing child configuration and an unsupported migrated-v6 extrusion-backed part likewise preserve parent/child provenance and fail before child geometry work. Child-local parts and nested local assemblies are admitted, but an active external descendant would cross a second document boundary and is rejected before nested resolution or child geometry/kernel work. A suppressed nested external descendant remains inert. If later child evaluation fails, every earlier acquired or intermediate shape is released exactly once, including work from an earlier child context. Successful product results retain their child shapes until product disposal. The supplied kernel is borrowed in both cases and is never disposed by the staged operation; verified resource bytes are cleared when its operation-scoped session ends.

Debugging workflow

  1. Preserve the full diagnostic object.
  2. Locate path and node in the serialized document.
  3. Check kernel capabilities before changing geometry.
  4. Use topology explanation functions for selector/reference failures.
  5. Reproduce with the smallest parameter/configuration context.
  6. Change a limit only after confirming the input is legitimate and bounded by infrastructure elsewhere.