> ## Documentation Index
> Fetch the complete documentation index at: https://invariant-cad.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Diagnostics and resource limits

> Handle structured failures and configure bounded document, topology, history, and artifact work.

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

```ts theme={"system"}
interface DiagnosticLocation {
  node?: string;
  path?: string;
  message: string;
}

interface Diagnostic {
  code: DiagnosticCode;
  severity: "info" | "warning" | "error";
  message: string;
  path?: string;
  related?: readonly DiagnosticLocation[];
  node?: string;
  hints?: readonly string[];
  details?: Readonly<Record<string, unknown>>;
}
```

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.

```ts theme={"system"}
import {
  design,
  mm,
  parseDocument,
  stringifyDocument,
  vec3,
} from "invariantcad";

const cad = design("bounded-input");
const box = cad.box("box", {
  size: vec3(mm(10), mm(20), mm(30)),
});
cad.output("box", box);

const json = stringifyDocument(cad.build());
const documentBytes = new TextEncoder().encode(json).byteLength;
const parsed = parseDocument(json, {
  limits: { maxDocumentBytes: documentBytes - 1 },
});
if (parsed.ok) {
  throw new Error("Expected the configured byte ceiling to reject the input");
}
const issue = parsed.diagnostics[0];
if (issue === undefined) {
  throw new Error("Expected a structured resource-limit diagnostic");
}

export const diagnosticsLimitSummary = {
  code: issue.code,
  severity: issue.severity,
  resource: issue.details?.resource,
  limit: issue.details?.limit,
  actual: issue.details?.actual,
};
console.log(diagnosticsLimitSummary);
```

The release gate compiles and executes the source module from
`examples/docs/diagnostics-and-resource-limits.ts`.

## Common code families

| Family              | Examples                                                                                                            | Typical action                                                                            |
| ------------------- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Document            | `IR_INVALID`, migration/validation errors                                                                           | Reject or migrate the input before evaluation                                             |
| Parameters          | unknown override, dependency cycle, bounds                                                                          | Correct IDs/formulas or override values                                                   |
| Kernel              | `KERNEL_CAPABILITY_MISSING`, `KERNEL_ERROR`                                                                         | Choose a compatible backend or inspect native failure details                             |
| Imported source     | `IMPORT_SOURCE_INVALID`                                                                                             | Correct the one-body definition, format/media pairing, units, or unsafe source descriptor |
| Resource resolution | `RESOURCE_RESOLVER_MISSING`, `RESOURCE_RESOLUTION_FAILED`, `RESOURCE_INTEGRITY_MISMATCH`, `RESOURCE_LIMIT_EXCEEDED` | Supply committed bytes, correct the resolver/digest/length, or review the byte ceiling    |
| Topology            | missing, ambiguous, fingerprint mismatch, limit exceeded                                                            | Refine selector/reference, recapture, or review limits                                    |
| Export              | `EXPORT_OPTIONS_INVALID` (unreleased 0.2), `EXPORT_UNSUPPORTED`                                                     | Correct option-relative paths or use a supported format/kernel                            |
| Physical data       | `MASS_DENSITY_MISSING`, `MASS_PROPERTIES_INVALID`                                                                   | Author valid density or correct geometry                                                  |
| BOM                 | missing/duplicate part number, missing material                                                                     | Fix manufacturing metadata; warnings may be non-fatal                                     |
| Cancellation        | aborted operation                                                                                                   | Stop the workflow or retry in a new scope                                                 |

## 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:

| Resource                |   Default |
| ----------------------- | --------: |
| Document bytes          |    64 MiB |
| Structural values       | 1,000,000 |
| Nesting depth           |       128 |
| Topology references     |    10,000 |
| Reference variants      |    20,000 |
| Stored adjacency links  | 1,000,000 |
| Stored evidence records | 1,000,000 |
| Topology query nodes    |   100,000 |

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:

| Ceiling                   | Staged product behavior                                                           |
| ------------------------- | --------------------------------------------------------------------------------- |
| `maxRequestedResourceIds` | Bounds distinct scoped requests retained by the session                           |
| `maxResolvedResources`    | Bounds distinct scoped resources resolved across every phase                      |
| `maxResourceBytes`        | Bounds each individual committed resource                                         |
| `maxTotalResourceBytes`   | Bounds all committed bytes retained across every phase                            |
| `maxExternalDocuments`    | Bounds distinct active external document resources before resolver or kernel work |

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.
