xanosdk command ends with an exit code, and off a terminal it also writes one JSON
document to stdout. The exit code says that something failed; the document says which thing.
In a script or CI job, branch on the exit code first and on error.code second. Never match on
the message text: messages are reworded between releases, codes are not.
Exit codes
A failure document’serror.exitCode always matches the process exit code.
Codes
3, 4, 5 and 6 share a shape: the deploy itself happened. Do not re-run the
whole deploy as if nothing landed. A signal that arrives while a write is on the wire ends the run
with 9, not 130, 143 or 129, because what you need to know next is “read before you
retry”.
JSON output
stdout carries one JSON document whenever it is not a terminal, or whenever you pass--json.
Progress and messages go to stderr, so a pipe or a CI log step reads clean JSON:
--help, xanosdk version (so
$(npx xanosdk version) works), and a command whose stdout is its data, such as export to
stdout or --path -. Those write a failure document only under --json, because appending one
to the data would corrupt it.
Every date in a --json document is ISO 8601 UTC, for example 2026-10-01T09:13:16.000Z.
The failure document
A command that fails under--json, or with stdout piped, writes this instead of its normal
document, so stdout is never empty:
SDK_ERROR is the code for any failure that has no code of its own yet. For those, exitCode
tells the kinds apart: 8 for a named thing that is missing or a network failure before any
write, 1 for the rest.
Set XANOSDK_DEBUG=1 to append the untouched server response to any failure message.
Operation outcome
The four release writes,release create, promote, tenant deploy and release transfer,
answer one question in one shape: does the outcome you asked for exist?
Each entry in
steps has its own completed: yes, no, unknown, or skipped for a step an
earlier failure kept from running. For promote, the verify step only checks the landing: a
verification that could not run leaves the landing yes.
Settling an unknown
unknown is settled by a read, never by a retry:
- Run the
resolveWithcommand. It is read-only. - Follow
resolveSteps, which says what to do with each answer the read can give. - Treat “absent” as proof only after
resolveNotBefore. Before then the server may still be finishing the write.
v1.4.0-a019) and reports success, so a second release create
after a lost answer can leave two releases. A second promote lands a second Xano branch.
Interrupted and declined runs
A run ended by a signal writesinterrupted: true. With a write on the wire the outcome is
unknown (exit 9); with none it is cancelled (exit 130, 143 or 129). Either way landed
says what the run had already landed.
A declined confirmation exits 0 and still writes its document: the operation commands write the
step as no, and the delete commands (tenant delete, ephemeral delete, release delete,
workspace branch delete) write deleted: false, declined: true.
Next
- Symptom by symptom, with the fix: Troubleshooting.
- Every
SDK_*code: Warning and error codes. - Using exit codes in a pipeline: CI/CD.