Skip to content
neuralSPOT-X
User guide
HELIA HUB

Troubleshooting

This page is organized around the messages NSX prints. If you have one in front of you, search this page for a distinctive fragment of it. Paths and names in the examples below stand in for whatever yours says.

Before anything else, run nsx doctor. A missing compiler or a J-Link pack that is not on PATH produces failures much further downstream than you would expect.

NSX app config not found: /home/you/nsx.yml
Run `nsx create-app <app-dir>` to create a new app.

configure, build, flash, view and clean locate the app by walking up from the working directory looking for nsx.yml. This message means the walk reached the top without finding one. Either cd into the app, pass --app-dir <path>, or pass the app as the positional argument, which also resolves names under ./examples in a source checkout.

Unable to determine target board from args or nsx.yml

The app’s manifest declares no target and you did not pass --board. Add a target.board or a targets.default to nsx.yml, or name a board on the command line. See Boards and targets.

App directory already exists and is not empty: /home/you/my_app

Pick a different directory, or pass --force to write into this one. --force overwrites the files NSX generates; it does not empty the directory first.

Unknown app template 'tflite'. Known templates: default, npu-tflm

The message lists what is available. See The app model.

Unable to infer --soc for board 'my_board'. Pass --soc explicitly.

The board is not one NSX can map to an SoC on its own, which normally means it is a board you are adding rather than a packaged one. Pass --soc, and see Add a board.

Unable to resolve dependency metadata for nsx.yml modules [nsx-audio]: ...
Run `nsx lock` with the required module sources available so nsx.lock can record the
full dependency closure.

NSX could not read a module’s manifest. In practice that is a network failure, a private repository you are not authenticated against, or a revision that no longer exists upstream. Resolution needs to reach every module’s source, because the manifests that describe the graph live in the module repositories rather than in NSX.

Dependency cycle detected at module 'nsx-foo'

Two modules require each other, directly or through a chain. This is a problem in the manifests, not in your app. If the modules are yours, break the cycle by moving the shared piece into a third module; see Custom modules.

Module 'nsx-uart' is already a direct dependency in nsx.yml

It is already listed. nsx module list shows what the app depends on directly. Note that a module can be present in the resolved graph as a transitive dependency without being a direct one, which is the usual reason this is surprising.

--board apollo4p_evb not in the app's supported targets (apollo510_evb)

nsx module add --board can only scope a dependency to a board the app already declares. Add the board to targets.supported first.

--frozen turns any disagreement between nsx.yml, nsx.lock and modules/ into an error instead of quietly correcting it. Use it when checking reproducibility, including in CI. After intentional dependency changes, update the lock and review the changes before checking again.

Vendored module 'my-module' content drifted from lock ...
Local module 'my-module' content drifted from lock ...
Local source for 'my-module' at /home/you/src/my-module has drifted ...

Something on disk no longer matches the content hash recorded in nsx.lock. If you changed the module on purpose, re-run nsx lock to record the new state. If you did not, nsx sync without --frozen restores it. A fetched module that was edited in modules/ fails the same way:

Module 'my-module' at modules/my-module does not match nsx.lock ...

A module missing from modules/, as on a fresh clone, is not drift: --frozen fetches it at the revision in nsx.lock and checks its content hash. If the upstream changed since the lock was written, the fetched copy is removed and the command fails:

Module 'my-module' fetched at its locked revision does not match nsx.lock ...

Re-run nsx lock to record the upstream as it is now, then review the change.

/home/you/my_app/nsx.lock not found. Run `nsx lock` first (or drop --frozen).

There is no lock to verify against. Without --frozen, nsx configure would have written one.

--sdk-root (/opt/AmbiqSuite) cannot be combined with --frozen: ... Drop one of the two flags.

An SDK tree pointed at by --sdk-root is not recorded in nsx.lock, so the build cannot be reproduced from the lock. NSX refuses the combination rather than producing a binary it cannot account for. See SDK foundation and overrides.

--sdk-root is not a directory: /opt/AmbiqSuit

A typo in the path, usually.

Missing build.ninja in build directory: /home/you/my_app/build/apollo510_evb

The build tree was never generated or has been partly deleted. Run nsx configure, or nsx clean --full followed by nsx build, which configures from scratch.

A compiler error inside a vendored module is a real compiler error: the sources under modules/ are the sources being compiled, and the path in the error message is the file to open. If you edited a vendored module to get past it, remember that nsx sync will restore the original.

/home/you/my_app/nsx.lock not found. Run `nsx lock` first.

nsx sbom and the lock-reading commands need a resolved graph. nsx configure writes one as a side effect; nsx lock writes one on its own.

No J-Link probes found.

nsx probes found nothing attached. Check the cable and that the J-Link pack is installed, then re-run nsx doctor, which checks for the SEGGER runtime specifically.

J-Link exited successfully for target 'my_app_flash' but printed no recognized flash
result: neither a 'Flash download: Total' summary nor a 'Skipped. Contents already match'
notice. The device was most likely programmed; this usually means the installed J-Link
Commander words its summary differently. Inspect the echoed J-Link output for what
actually happened.

NSX reads J-Link’s own output to decide whether programming happened, and different J-Link Commander releases word the summary differently. The message says what to do: read the echoed J-Link output above it. The exit status alone does not confirm programming. Check the device output or repeat the flash with a supported J-Link version before treating the image as verified.

With more than one probe attached, pass --probe-serial to say which one. That always forces a reconfigure, because the serial is baked into the generated SEGGER command files.

The most common cause is not an error at all. On apollo3p, apollo4l, apollo4p and apollo510b, nsx view attaches without resetting the target, so if the firmware already ran past its output you see an idle stream. NSX says so when it happens:

Using attach-only SWO view for this secure-reset SoC; flash first or pass --reset-on-open to force a reset.

Flash first, or pass --reset-on-open. On other SoCs view resets by default, and --reset-delay-ms controls how long it waits before reading.

If the firmware never enabled SWO output, nothing will appear regardless. The generated app calls nsx_itm_printf_enable() before its first nsx_printf(); see System initialization.

Unable to resolve the SEGGER SWO viewer command for target 'my_app_view' from /home/you/my_app/build/apollo510_evb/build.ninja

NSX reads the viewer invocation out of the generated Ninja file and could not find it. That means the build tree is stale or was generated by a different NSX version. Re-run nsx configure.

Cannot open capture file /var/log/swo.txt: Permission denied

--capture could not open the path for writing. The underlying reason is quoted after the colon.

  • -v can be repeated to increase verbosity, which shows the subprocesses NSX runs.
  • The generated tree is ordinary CMake and Ninja, so ninja -C build/<board> -v shows the exact compiler command lines.
  • nsx doctor --json and nsx commands --json give machine-readable state if you are scripting around a failure. See the Python API guide.