# Troubleshooting

Start with the failing stage and preserve its message, configuration and model
identity. Typed conversion failures raise a `HeliaAotError` subclass that may
include an actionable hint. Some input failures still raise ordinary exceptions, including
a missing golden archive and an unknown transform name; a traceback alone does
not tell you whether the model, configuration or compiler is at fault.

## Find the next check

| Symptom | Check | Next action |
| --- | --- | --- |
| Configuration fails before conversion | Field names, enum values and the validation message | Compare the setting with the [Configuration reference](https://ambiqai.github.io/helia-aot/reference/configuration/). |
| A placement rule has no effect | Tensor kind spelling, actual tensor id and rule precedence | Use lowercase `constant`, `persistent` or `scratch`; specify both type and id to override a type rule. |
| A platform field is ignored | Whether `platform.name` is registered | Use memory constraints for this model's budget, or define a complete custom target under an unregistered name. |
| No kernel applies | The node's dtype, shape, options and target capabilities | Check [operator restrictions](https://ambiqai.github.io/helia-aot/reference/operators/); precision is determined by model tensors. |
| Golden archive cannot load | Path relative to the process, numeric arrays and required `input_N`/`output_N` keys | Regenerate or correct the archive; keep verification enabled when claiming numerical agreement. |
| `model_run` returns `14` | Successful `model_init` for the context | Check initialization's return value; calling `context_init` alone is insufficient. |
| `model_run` returns `200` | Staged constants and hydration latch | Complete hydration and mark it at the helper's call point during initialization. |
| Outputs mismatch | Input bytes, initial state, iteration count, golden source and tolerance units | Reproduce the first mismatch and inspect those contracts before changing a tolerance. |

If the message remains unexplained, report the full traceback, package version,
target, resolved configuration and the smallest model or node description that
reproduces it. Include whether failure occurred during conversion, build,
initialization or inference.

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | The conversion finished. |
| `1` | A typed conversion failure or an unhandled exception; inspect stderr. |
| `2` | Configuration validation failed, with one message per field. |
| `130` | Interrupted. |

## The error classes

Every class below also inherits the matching standard-library exception, so
code already catching `ValueError` or `FileNotFoundError` keeps working. The
class list, with the base types and docstrings as the code declares them, is in
the [Errors reference](https://ambiqai.github.io/helia-aot/reference/errors/).

### `HeliaAotError`

The base class for typed conversion failures. Catch it to handle that family.
Seeing it raised directly, rather than one of its subclasses, is unusual.

### `ConfigValueError`

A configuration value is invalid for the requested conversion. Also a
`ValueError`.

Read the hint: it names the setting. This is also the error an operator raises
when no kernel applies to a node, in which case the hint asks you to check that
node's dtype, shape and options against what a kernel supports: the
[operator catalog](https://ambiqai.github.io/helia-aot/reference/operators/) is the list.

### `ModelLoadError`

The input model could not be found or parsed. Also a `FileNotFoundError`.

Check `model.path`. For a file that exists, check the model format and subgraph
index as well as
the parser message; unsupported structure or corrupt input needs a different
remedy from a missing path.

### `UnsupportedModelError`

The model uses a structure or a dtype heliaAOT cannot lower. Also a
`ValueError`.

The graph was recognized, so the message names the construct and the hint
states the supported form. Read the hint before changing anything: the fix is
usually in how the model was exported, not in the conversion. A recurrent loop
whose weights are dequantized inside the loop body, for instance, is a
weight-only FP16 export rather than a native FP16 model; see
[Precision](https://ambiqai.github.io/helia-aot/guide/precision/#what-is-and-is-not-a-float-model).

**Unresolved dynamic tensor shapes after propagation.** Raised as an
`UnsupportedModelError` during Analyze when a tensor's LiteRT
`shape_signature` holds a negative dimension that shape propagation could
neither resolve from the concrete input shapes nor confirm. The message
lists the tensors by their LiteRT indices in the subgraph, written as
strings, so `0` is the first tensor. A dynamic batch dimension on the model
input resolves on its own, and shape-building subgraphs rooted at `SHAPE`
are evaluated together with shapes during propagation. The usual cause is a
shape that depends on a runtime value. Fix the export so the shape is concrete; the hint says
the same. Run with `--verbose 2` to see, per tensor, the signature and the
shape propagation reached.

### `OutputExistsError`

An output path already exists and `--force` was not given. Also a
`FileExistsError`.

Pass `--force` to overwrite, or point `module.path` somewhere else. The same
error guards the residency report.

### `GoldenDataKeyError`

A supplied golden-data archive is missing a required tensor key. Also a
`KeyError`.

Regenerate the archive with an `input_N` and an `output_N` entry for every
model input and output, which is what the hint asks for.

### `TemplateRenderError`

A codegen template referenced context its handler did not supply. Also a
`RuntimeError`.

This is a heliaAOT defect, not a problem with your model, and the hint says so.
The error names the operator and, where it can, the template and the line. It
is reachable from a valid model, so please report it with the model or a
description of the failing node.

## Before the errors: the warnings

Warnings can explain why a setting did not take effect. Read them before
trusting the resolved configuration or resulting plan.

**An unknown nested key.** It produces a deprecation warning with a
did-you-mean suggestion and is dropped. Only the top-level `ConvertArgs` keys
are strict today; nested blocks will become strict later. Fix the spelling now.

**An unknown tensor attribute.** The keys under `memory.tensors[].attributes`
are checked the same way.

**Ignored platform fields.** For a registered target, configured `cpu`,
`speeds`, `capabilities`, `preferred_memory_order` and `min_alignment` do not
override the registration. The converter warns and uses the registered
definition. `memories` is the exception: the sizes it names replace the
target's for that conversion. See [Choosing a target](https://ambiqai.github.io/helia-aot/guide/configuring/#choosing-a-target).

Warnings raised while the configuration is loading are buffered and replayed
after logging is set up, so they appear after the first milestones rather than
before them.

## When there is no error at all

Some problems do not raise.

**A rule that did not apply.** The rule matched nothing, or a higher-priority
rule overrode it. Type-only rules outrank id-only rules; later position decides
only between equally specific rules. Tensor kinds match lowercase spellings
exactly. Run with `--verbose 2` to inspect resolved operator attributes, and use
the residency report to verify tensor placement and ids. See
[precedence](https://ambiqai.github.io/helia-aot/guide/configuring/#precedence).

**A module that compiles but does not match the reference.** Compiling is not
validation. Enable `test.enabled`, keep `skip_verification: false` and choose
trusted golden outputs or the host-interpreter oracle. The generated test then
checks agreement within `test.tolerance`; see the [oracle and tolerance
limits](https://ambiqai.github.io/helia-aot/guide/testing/#the-three-oracles).

**`model_run` returning 14 or 200.** Status `14` means model initialization
has not completed successfully; `context_init` alone does not enable a run.
Status `200` means staged constants are not marked hydrated after a successful
initialization. A replacement hydrate helper must finish populating the arenas
and call the mark-hydrated function before returning success, because operator
init hooks may immediately read those constants. Marking before `model_init`
is ineffective: its `context_init` call clears the latch. See
[the hydration contract](https://ambiqai.github.io/helia-aot/guide/memory-placement/#the-hydration-contract).

**A build that will not link or compile.** Check the ns-cmsis-nn version floor
the generated header enforces, and the float switches the module requires. See
[Precision](https://ambiqai.github.io/helia-aot/guide/precision/#the-library-build-switch).
