CadResult; invalid direct authoring calls can throw TypeError or
RangeError immediately.
Diagnostic shape
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. Paths from parsing and
validateDocument are JSON Pointers: an ID segment that contains ~ or / is
escaped as ~0 or ~1, so a node named a/b is reported under
/nodes/a~1b. Some diagnostics raised later, during evaluation or feature
hashing, still place such IDs unescaped, so prefer IDs without ~ or /.
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.examples/docs/diagnostics-and-resource-limits.ts.
Document parsing stops measuring as soon as a ceiling is exceeded, so
details.actual for maxDocumentBytes, maxStructuralValues, and
maxNestingDepth is the size observed at that point: a lower bound on the full
input, not its total size.
Common code families
Authoring exceptions
These are programmer mistakes and throw immediately:- duplicate IDs
- cross-design references, including parameters inside expressions
- wrong-dimensional expressions
- a face selection passed to a fillet
- an empty Boolean tool array
- a configuration with no overrides
- non-positive or non-finite numeric sketch and path tolerances
segmentsordivisionsvalues outside the document grammar- unsupported literal authoring option values
TOPOLOGY_SELECTOR_INVALID, instead of being thrown while authoring.
For the public imported-body workflow, invalid caller definitions
and unsafe source descriptors return IMPORT_SOURCE_INVALID; invalid
evaluation options return IR_INVALID with a path under /options. 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, so later reads cannot change what
was validated. Cycles, sparse arrays, non-array objects whose prototype is
neither
Object.prototype nor null, and work beyond the configured bounds
fail before schema traversal.
For Documents v1–v6 the copy neutralizes rather than rejects the remaining
JavaScript-only shapes: an accessor property is read once and its value is
captured, only enumerable own string keys are copied, and an instance of an
Array subclass is copied into a plain array. Only the staged Document v7
snapshot is stricter. It never invokes a getter and rejects accessor,
non-enumerable, and symbol properties, as well as arrays that do not use the
intrinsic array prototype.
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.Assembly evaluation limits
PublicEvaluator.evaluate(...) flattens assemblies into occurrence records.
Document preflight bounds the document, not that expanded tree, so evaluation
charges three fixed ceilings before allocating records:
Crossing one fails with
RESOURCE_LIMIT_EXCEEDED at the assembly node and the
instance that would exceed it, with details.resource, details.limit, and
details.actual. See occurrence ceilings
for how records are counted. The ceilings are not configurable on the public
evaluator.
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 staged work, not a public 0.2.0
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.
The same top-level provenance applies to deferred failures raised later by an
evaluated assembly, such as an occurrence mesh failure, an occurrence
mass-property failure, or a BOM warning. For a fixed-subassembly leaf,
childAssemblyNode names the child assembly that owns the leaf instance and
childPath points at that instance’s component in the child document; a child
diagnostic’s own path, when it has one, moves to childDiagnosticPath. A
deferred assembly mesh failure names the assembly being meshed as
assemblyOutput, because output names the external component.
EvaluatedProductDocumentV7.mesh() and export(...) rethrow that structured
assembly failure unchanged instead of reducing it to a message string, 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
- Preserve the full diagnostic object.
- Locate
pathandnodein the serialized document. - Check kernel capabilities before changing geometry.
- Use topology explanation functions for selector/reference failures.
- Reproduce with the smallest parameter/configuration context.
- Change a limit only after confirming the input is legitimate and bounded by infrastructure elsewhere.