Skip to content
COMA

JSON output and errors

The --json envelope every COMA command writes, how stdout and stderr are used, and the stable error codes with their exit codes.

Every COMA command takes --json. Scripts and coding agents can rely on the shape below and on the error codes: they are part of COMA's public interface.

Streams

Human outputWith --json
stdoutThe resultOnly the result envelope
stderrWarnings, progress, logs and errorsLogs, and the error envelope on failure

With --json, warnings are not printed to stderr; they are collected in the result's warnings array. Colour is off. Logs (--verbose, --debug, --trace) still go to stderr, so stdout always parses as one JSON document.

Success

coma machine list --json
{
  "apiVersion": "coma.sh/cli/v1alpha1",
  "kind": "MachineList",
  "requestId": "req_01M437ZZEA4TBZSA8M7XMSGSDR",
  "data": [],
  "warnings": [],
  "meta": {
    "comaVersion": "v0.1.0-rc.4-3-g07087e6"
  }
}
FieldValue
apiVersioncoma.sh/cli/v1alpha1, the version of this contract
kindThe result type, for example MachineList, DoctorReport, WorkspaceStatus, PortList
requestIdreq_ followed by a ULID. The same ID appears in this invocation's log lines
dataThe result. Its shape depends on kind
warningsStrings; always present, empty when there are none
meta.comaVersionThe version of the coma that wrote it

Keys are camelCase. Byte counts are numbers of bytes.

Failure

On failure, stdout is empty and stderr holds one error envelope. The exit code follows the error code (table below).

coma machine inspect nope --json
{
  "apiVersion": "coma.sh/cli/v1alpha1",
  "kind": "Error",
  "requestId": "req_01M437ZZDJC3MGMGBZ3DS9QKJZ",
  "error": {
    "code": "machine_not_found",
    "message": "machine \"nope\" not found",
    "retryable": false,
    "details": {
      "hint": "run `coma machine list`",
      "machine": "nope"
    }
  }
}
FieldValue
error.codeA stable, lower snake_case code
error.messageWhat failed, for people. Do not parse it
error.retryabletrue when trying again may succeed, for example when the machine could not be reached
error.detailsAn object, possibly empty. hint says what to run next; other keys depend on the code, such as diagnostics for an invalid coma.yaml or suggestions for a mistyped command

Usage errors, such as an unknown command or flag, use the same envelope with invalid_argument when --json appears anywhere before --.

Doctor commands

Commands that run checks write their report to stdout even when a check fails, then exit with 10 (doctor_failed):

  • coma doctor writes only the DoctorReport.
  • coma endpoint doctor and coma docker-context verify also write a doctor_failed error envelope to stderr. verify reports a context changed outside COMA as docker_context_drifted instead.

Passthrough

coma docker and coma podman run the engine's own CLI on the machine. Their output is that CLI's output, and they exit with its exit status.

Error codes

CodeExitMeaning
invalid_argument2A command, flag, argument or environment value is wrong
invalid_config10COMA's config file cannot be read or has an invalid value
not_found3Something COMA needs is missing, such as the coma-sync helper
already_exists4The thing to create exists already, such as a coma.yaml without --force
conflict4The action conflicts with the current state, such as comad already running
permission_denied5COMA cannot read or write a local file or directory
unauthenticated5Reserved; no current command returns it
unsupported8The request is not supported, such as a coma-sync helper from another release
not_implemented8Reserved; no current command returns it
timeout7An operation ran past its time limit
lock_timeout7Another coma process held the state lock too long
network_unavailable6Reserved; no current command returns it
state_corrupt10The local state database, or a record in it, is corrupt
migration_failed10The local state database could not be upgraded
state_schema_too_new10The state database was written by a newer coma
doctor_failed10A check in doctor, endpoint doctor or docker-context verify failed
interrupted130Ctrl-C or SIGTERM stopped the command
internal1A bug in COMA, or a failure with no more specific code
context_not_found3No COMA context with that name
context_already_exists4A COMA context with that name exists
confirmation_required2The action needs confirmation and there is no terminal to ask; re-run with --yes
machine_not_found3No machine with that name
machine_already_exists4A machine with that name exists
machine_unreachable6COMA cannot reach the machine over SSH
machine_auth_failed5SSH authentication to the machine failed
machine_in_use4Contexts still use the machine; remove with --detach to clear them
machine_target_required2No machine given, and the current context names none
machine_discovery_failed6COMA reached the machine but could not inventory or prepare it
machine_unsupported_os8The machine does not run Linux
ssh_host_key_unknown5The host key was not confirmed on first use; pass --host-key
ssh_host_key_mismatch5The machine's host key changed since it was added
ssh_key_unavailable5An SSH private key cannot be read or parsed
ssh_proxy_failed6The SSH configuration needs a proxy COMA does not support, such as ProxyJump
bootstrap_plan_failed8COMA cannot plan the bootstrap, for example on a distribution without apt
bootstrap_failed6A bootstrap step failed; run bootstrap again to resume
bootstrap_privilege_required5A bootstrap step needs passwordless sudo on the machine
engine_not_found3The requested engine, or any engine, is not on the machine
engine_selection_required2The engine is ambiguous or missing; pass --engine
engine_unavailable6The machine has an engine, but none is working
engine_permission_denied5The SSH user is not allowed to use the engine
endpoint_not_found3No endpoint with that name or ID
endpoint_backend_unavailable6The engine did not answer through the endpoint
endpoint_socket_conflict4The endpoint's socket path is in use or is not a socket
docker_context_conflict4A Docker context with that name exists and COMA did not create it; use --replace
docker_context_not_found3COMA manages no Docker context with that name
docker_context_drifted4A COMA Docker context was changed outside COMA
daemon_unavailable6comad is not running or cannot be reached or started
local_port_in_use4A local port is taken, by another program or another workspace
sync_mode_unsupported8The sync mode needs the Mutagen engine, and comad runs the built-in one
workspace_manifest_not_found3No coma.yaml here or in a parent directory, or --file does not exist
workspace_manifest_ambiguous2Both coma.yaml and coma.yml exist, or several workspaces share the name
workspace_manifest_invalid2coma.yaml is invalid; details.diagnostics lists each problem
workspace_api_version_unsupported8coma.yaml uses an apiVersion this COMA cannot read
workspace_not_found3The workspace is not registered; run coma workspace up
workspace_target_required2No machine in coma.yaml, --machine or the current context
workspace_target_kind_unsupported8coma.yaml targets a pool or cluster
workspace_plan_blocked4workspace up cannot run the plan, for example bidirectional sync without your opt-in
workspace_delete_blocked4workspace delete --remote cannot remove the copy on the machine

A code this table does not list maps to exit 1.

Refusals inside Docker errors

When COMA refuses a container request from the Docker CLI, Compose or an SDK, the refusal comes back through the engine API, so the client shows it in its own error. COMA's message names a code in parentheses, for example:

CodeMeaning
sync_bind_source_unmanagedA bind source is outside every directory synced to this machine
sync_bind_source_missingA bind source is not on the machine, for example because sync ignores it
sync_barrier_timeoutYour latest changes were not on the machine in time; the container was not created

These are not coma exit codes: the client that made the request decides its own exit status.

On this page