This page owns handled-error interpretation, retry safety, and recovery guidance. Read the command reference for successful command behavior.
Every handled subcommand failure ends with exactly one JSON object on standard error. plan compile may first write
progress lines; machine consumers can remove only lines beginning with the exact First Draft: prefix and parse the
remaining JSON document. Branch on the stable error value rather than the human-readable detail.
Handled output never includes command arguments, local Plan bytes, raw artifact bytes, raw filesystem or network
errors, or unvalidated response bodies. local_state_not_saved is the sole exception to private-state redaction:
its recovery_state is required to repair the accepted ETag locally. Root-level and command-group usage failures
remain human-readable text on standard error with exit 2. Unexpected programming defects remain loud.
plan compile supplies phase: "push" | "compilation" | "publication" when request_outcome_unknown requires
phase-specific recovery:
phase: "push"means the Plan mutation may have been accepted. Stop and reconcile local Head state. Until First Draft has a Foundation Plan Head reconciliation endpoint, an accepted request whose response cannot be verified may require manual recovery. Do not construct an ETag from the Plan digest or trust an unverified response.phase: "compilation"means a direct--outputCompilation may have started, but its retained identity is unknown. The CLI never repeats thatPOST. Do not start another Compilation until the Project is reconciled through First Draft or an operator can identify the retained work.phase: "publication"means the singleton Publication mutation was not resolved. Do not run concurrent Compile commands. After the prior invocation exits, wait and rerunplan compilewith unchanged Plan bytes to safely reconcile or resume the retained singleton.
plan push also reports request_outcome_unknown if a failure happens after sending its request. Local state remains
unchanged. Stop and reconcile rather than assuming the request failed and repeating the mutation.
If a verified Plan response cannot replace local state, preserve the printed recovery_state; an adjacent .tmp
file may contain the same private recovery copy. Do not push again until the accepted ETag state is repaired.
A network failure from plan status is safe to retry a bounded number of times because the command sends only
GET requests. If status_unavailable persists, inspect the API origin pinned in .firstdraft/state.json.
invalid_server_response instead means the response violated the CLI/server contract; retrying the unchanged read
will not repair it.
Only the lower-level compilation status <compilation-id> command is read-only. Its
compilation_status_unavailable result is safe to retry a bounded number of times;
invalid_compilation_status requires contract reconciliation. A wait stops rather than following a changed
analysis or Compilation identity. This read-only retry guidance does not apply to plan compile --output, which
starts a new Compilation after analysis.
Do not blindly rerun plan compile --output after its Compilation start was accepted or may have been accepted.
That command creates new work; it is not a retained-Compilation reconciliation command.
If request_outcome_unknown reports phase: "compilation", the start request did not yield a validated retained
ID. The CLI sent exactly one POST and did not retry it. Stop until First Draft or an operator can reconcile the
Project and identify whether work was retained.
Once the start response has yielded a validated retained Compilation, later status, artifact, authentication, and
materialization failure envelopes include that last validated projection as current. Preserve
current.compilation.id and recover without creating duplicate work:
- after
compilation_status_unavailable, usefirstdraft compilation status <current.compilation.id>; this lower-level read is safe to retry boundedly; - after
invalid_compilation_statusorinvalid_artifact, preserve the retained ID and reconcile the CLI/Service contract instead of retrying the unchanged invalid read; - after
artifact_unavailable, wait if appropriate and usefirstdraft compilation download <current.compilation.id> --output <new-absent-path>; and - after
materialization_failed, repair the destination condition, then use the same lower-level download command with a new absent path. A root-output attempt whose transaction fully rolled back may instead retry that retained download with--output .;reason: "root_rollback_incomplete"requires reconciliation of the retained.firstdraft-root-outputjournal before another root attempt. Only that reason requires manual reconciliation: do not delete its journal or run Git restoration commands; read its versioned record, restore the exact listed index and path identities, verify its original snapshot, and then remove the transaction directory. A journal whose phase records no irreversible operation is safe to remove. After.firstdrafthas moved successfully underdesign, run retained status and later Plan commands fromdesign, not from the generated application root.
After compilation_wait_timed_out, retained work may still continue. Use
firstdraft compilation status <current.compilation.id> for one read-only status check; do not rerun
plan compile --output. compilation_failed, compilation_cancelled, and compilation_changed already carry the
validated current projection appropriate to their stopping boundary. Authentication recovery may refresh the
credential, but it must continue from the retained ID rather than starting another Compilation.
The Publication is a Project singleton. If its initial conditional PUT is ambiguous, the CLI attempts one
read-only singleton GET and never automatically repeats the mutation in that invocation.
After publication_status_unavailable or publication_wait_timed_out, retained work may still continue. Do not run
concurrent Compile commands. Wait, then rerun plan compile with unchanged Plan bytes; the conditional request
safely reconciles or resumes the same retained singleton without creating another Compilation, repository, or push.
The same recovery applies when an invocation exits after an unresolved Publication start.
A GitHub preflight retry with no retry_at is paused and requires operator recovery. publication_failed and
publication_cancelled are terminal; inspect the validated phase and failure information rather than blindly
retrying. publication_changed means the pinned Publication identity or provenance changed, so the CLI deliberately
stopped without following the replacement.
| Commands | error |
Exit | Meaning |
|---|---|---|---|
| Any leaf command | invalid_arguments |
2 | Syntax was invalid; no request was made. |
plan init |
local_initialization_failed |
1 | Initialization failed without overwriting an existing path. |
plan push, plan compile |
invalid_configuration |
2 | API origin or saved Head state is incompatible. |
| Network commands | authentication_required |
1 | The token is missing or First Draft returned a validated authentication problem. |
Plan commands, compilation * |
local_input_unreadable |
1 | Required local Plan or private state could not be read. |
| Status, Compile, Compilation commands | project_not_pushed |
1 | No API origin is pinned for the local Project. |
plan push, plan compile |
request_outcome_unknown |
1 | A mutation or its response could not be verified; plan compile identifies its mutation phase. |
plan push, plan compile |
local_state_not_saved |
1 | The Plan was accepted but the private ETag state could not be replaced; includes recovery_state. |
plan push, plan compile |
server_rejected |
1 | First Draft returned validated Plan diagnostics or rejected the request with a validated problem. |
plan status |
server_rejected |
1 | First Draft rejected the analysis status request with a validated non-authentication problem. |
plan status |
status_unavailable, invalid_server_response |
1 | The analysis read failed or violated its protocol. |
plan compile |
analysis_status_unavailable, invalid_analysis_status, analysis_status_rejected |
1 | The bounded analysis read failed, was invalid, or was rejected. |
| Analysis waits | analysis_changed, wait_timed_out, analysis_wait_timed_out |
1 | The pinned analysis changed or remained processing at the deadline. |
plan compile |
plan_not_valid |
1 | Analysis completed without valid; current contains diagnostics and status. |
plan compile |
local_plan_changed |
1 | Local bytes or saved state changed after acceptance, before the selected mutation. |
plan compile --output |
compilation_start_rejected, compilation_status_unavailable, invalid_compilation_status |
1 | Direct start was rejected or retained status failed; post-start errors include current. |
plan compile --output |
compilation_changed, compilation_wait_timed_out, compilation_failed, compilation_cancelled |
1 | The pinned direct Compilation changed, timed out, failed, or was cancelled. |
plan compile |
publication_start_rejected, publication_status_unavailable, invalid_publication_status |
1 | Publication start or status failed its validated transport contract. |
plan compile |
publication_changed, publication_wait_timed_out, publication_failed, publication_cancelled |
1 | The pinned Publication changed, timed out, or reached a non-success terminal state. |
compilation status, compilation download |
compilation_status_unavailable, invalid_compilation_status |
1 | The retained status could not be read or violated its exact contract. |
compilation status --wait |
compilation_changed, compilation_wait_timed_out |
1 | Retained identity/provenance changed or the wait ended. |
compilation download |
compilation_not_succeeded |
1 | Status was not succeeded; no artifact request was made. |
| Download commands | artifact_unavailable, invalid_artifact |
1 | Artifact transport or integrity validation failed; direct Compile post-start errors include current. |
| Download commands | invalid_output_path |
2 | The absent destination or root-adoption preconditions failed; reason identifies the stable refusal. |
| Download commands | materialization_failed |
1 | The output changed or its transaction failed; reason identifies incomplete rollback when applicable. |
Root-output invalid_output_path.reason values are destination_exists, root_not_real, root_not_writable,
root_platform_unsupported, root_reserved_path, root_entry_unsupported, root_enclosing_worktree,
root_git_unavailable, root_git_unsupported, root_git_dirty, root_ignore_not_preserved, and root_busy. Git
refusing discovery, including a safe.directory refusal, is root_git_unavailable; a discovered but unsupported
Git shape such as a submodule is root_git_unsupported. Root-output materialization_failed.reason values are
output_changed, root_artifact_collision, root_ignore_changed, root_transaction_failed, and
root_rollback_incomplete.