Exit codes
| Code | When |
|---|
0 | Success, including a --until match or the last --expect match |
1 | Any other failure. espx prints one error: line on stderr that says what to do next |
124 | --timeout ran out, with the output up to that point still printed (the coreutils timeout convention) |
130 | A child process was killed by a signal, usually your Ctrl+C reaching cargo or espflash. espx prints nothing more |
124 comes from --timeout on run, monitor and replay, whether or not there was a pattern to wait for. A rejected line (--reject) and a stream that ends with an expectation still pending are both 1.
espx doctor reports missing tools in its output and exits 0 either way. Read its --json output, or each check's status, to fail a script on a missing tool.
Error codes
Every error espx can raise has a stable code, the same name in snake case across the CLI, the MCP server and the board hub. The CLI prints only the message. The code appears in:
- MCP tool results, as
error.code in the structured content.
- The agent audit log, as
detail.code on a denied or failed call.
- The JSON Schema, as the
ErrorCode type in schema/espx.json.
Renaming a code is a breaking change, so these are safe to match on.
Projects and setup
| Code | Meaning |
|---|
not_project | The directory has no Cargo.toml. Run espx new or pass --dir |
rust_not_found | rustup and cargo are missing |
xtensa_toolchain_missing | An Xtensa chip or project needs the esp toolchain. Run espx setup --chip <chip> |
unknown_chip | Not an id from espx chips |
unknown_board | Not an id from espx boards |
board_chip_mismatch | --board and --chip disagree |
bad_project_name | The name is not a valid project name; the message says why |
project_exists | The project folder already exists |
not_a_directory | The location is a file, not a folder |
dependencies | No Cargo.lock to read. Build first |
tool_missing | A tool espx needs is not installed. Run espx setup |
tool_unavailable | The mirror publishes no build of a tool for this platform |
unsupported_platform | No espx tools for this OS and architecture |
shell_unsupported | --shell only edits zsh and bash configs |
nothing_selected | espx uninstall with no flag and no -i |
not_a_tty | -i without a terminal |
Downloads and updates
| Code | Meaning |
|---|
fetch | A download failed |
manifest | The release or tool server answered with something espx cannot read |
archive_missing | A downloaded archive did not contain the expected binary. Nothing was installed |
checksum_mismatch | A download did not match its SHA-256. Nothing was installed |
install_failed | espx could not replace a binary on disk |
Builds
| Code | Meaning |
|---|
build_failed | cargo reported compile errors, or exited non-zero |
image_too_large | The image does not fit the app partition. Nothing was flashed |
Boards
| Code | Meaning |
|---|
port_required | No board, or several and none chosen. Pass --port or bind one |
board_not_attached | The board named by a flag or by [board] id is not connected |
board_unreachable | espx could not talk to the board; check the cable and that nothing else holds the port |
upload_corrupted | The bootloader received corrupted data, typically a WCH bridge on macOS's built-in driver |
board_leased | Another holder (a flash, an agent) is using the board |
board_gone | The board did not come back after a flash or reset. Press reset or replug it |
not_attached | Nothing is monitoring the board. Attach first |
session_closed | The monitor session closed. Attach again |
bad_board_name | The name has characters a board name cannot have |
name_taken | Another board already has that name |
Monitor and scripts
| Code | Meaning |
|---|
bad_pattern | A --until, --expect or --reject regex does not compile |
bad_duration | --timeout is not a duration like 30s or 2m |
timeout | The timeout ran out (exit 124) |
monitor_closed | The stream ended before the pending pattern matched |
rejected | A line matched a --reject pattern |
monitor_extra_args | Arguments after -- on monitor together with flags that make espx read the port itself |
recording | A recording file could not be read |
Configuration and agents
| Code | Meaning |
|---|
config | espx.toml or boards.toml has an error; the message names the file, line and key |
policy_denied | The [agent] policy does not let an agent do this to this board; the message names the keys to set |
policy_not_editable | The [agent] policy is written as an inline table or with dotted keys, so espx cannot edit it in place |
client_config | An MCP client's config file cannot be read or parsed |
client_not_found | The claude or codex CLI is not installed where espx looks |
client_command_failed | claude mcp add or codex mcp add failed |
espx_not_found | The desktop app cannot find the espx binary that MCP clients start |
The board hub
| Code | Meaning |
|---|
hub_unreachable | The espx process serving the board hub went away. Run the command again |
hub_served | Another espx process already serves the board hub |
General
| Code | Meaning |
|---|
command_failed | A child command failed, or a tool result failed without an espx error (a cancelled job, a rejected run) |
spawn | espx could not start a program |
env_capture | Sourcing ~/.espx/export-esp.sh failed |
write_failed | A file could not be written |
delete_failed | A file could not be deleted |
interrupted | A child was killed by a signal (exit 130) |
io | Any other I/O error |
The MCP server adds one code of its own, invalid_arguments, for a tool call whose arguments do not match the tool's schema.