Appearance
Error Codes
Every error raised by nubos-pilot is a NubosPilotError with a stable code string, a human-readable message, and an optional details object. Callers (workflows, plan-checker, test suites) match on err.code verbatim, never on the message.
js
class NubosPilotError extends Error {
constructor(code, message, details) {
super(message);
this.name = 'NubosPilotError';
this.code = code;
this.details = details;
}
}The codes below are grouped by source module.
Core / lifecycle
| Code | Source | Meaning |
|---|---|---|
not-in-project | lib/core.cjs | projectStateDir(cwd) could not find a .nubos-pilot/ ancestor. |
lock-timeout | lib/core.cjs | withFileLock could not acquire the lock within timeoutMs. |
unknown-command | np-tools.cjs | Top-level dispatch received an unrecognized command name. |
unknown-init-workflow | np-tools.cjs | init <workflow> dispatched to an unregistered workflow. |
Layout / IDs
| Code | Source | Meaning |
|---|---|---|
layout-invalid-number | lib/layout.cjs | Milestone/slice/task number is not a non-negative integer. |
layout-invalid-id | lib/layout.cjs | ID string does not match the expected shape (M<NNN>, S<NNN>, T<NNNN>, or M<NNN>-S<NNN>[-T<NNNN>]). |
layout-invalid-slug | lib/layout.cjs | Slug does not match /^[a-z0-9-]+$/. |
layout-slice-slug-mismatch | lib/layout.cjs | Existing slice directory has a slug different from the one requested. |
Roadmap / milestone
| Code | Source | Meaning |
|---|---|---|
roadmap-parse-error | lib/roadmap.cjs | roadmap.yaml unreadable or invalid YAML. |
roadmap-too-large | lib/roadmap.cjs | roadmap.yaml exceeds 1 MB cap. |
roadmap-invalid-milestone | lib/roadmap.cjs | Milestone input missing id. |
roadmap-duplicate-milestone | lib/roadmap.cjs | Milestone id already exists. |
roadmap-milestone-not-found | lib/roadmap.cjs | Referenced milestone id does not exist. |
roadmap-invalid-slug | lib/roadmap.cjs | Phase slug (legacy schema) missing or invalid. |
roadmap-invalid-description | lib/roadmap.cjs | Backlog description empty or contains YAML separator pattern. |
roadmap-description-too-long | lib/roadmap.cjs | Backlog description exceeds 500 chars. |
phase-not-found | lib/roadmap.cjs | getPhase(n) — no milestone with that number/id. |
Tasks
| Code | Source | Meaning |
|---|---|---|
tasks-invalid-frontmatter | lib/tasks.cjs | Task frontmatter missing required field or wrong type. |
tasks-invalid-status | lib/tasks.cjs | status value not in {pending, in-progress, done, skipped, parked}. |
tasks-invalid-tier | lib/tasks.cjs | tier value not in {haiku, sonnet, opus}. |
tasks-invalid-owner | lib/tasks.cjs | owner value not recognized. |
tasks-unknown-dep | lib/tasks.cjs | depends_on references a task id that does not exist in the graph. |
tasks-cyclic | lib/tasks.cjs | loadTaskGraph detected a dependency cycle. |
task-frontmatter-missing | lib/tasks.cjs | Task file has no frontmatter block at all. |
task-status-line-missing | lib/tasks.cjs | Task body has no status: line where one is required. |
invalid-task-status | lib/tasks.cjs | Status transition violates the lifecycle state machine. |
task-not-found | lib/tasks.cjs | Task id not present in the loaded graph / directory. |
Agents
| Code | Source | Meaning |
|---|---|---|
agent-not-found | lib/agents.cjs | loadAgent(name) could not find agents/<name>.md. |
agent-invalid-frontmatter | lib/agents.cjs | Required field missing, or name does not match filename stem. |
agent-forbidden-field | lib/agents.cjs | Frontmatter contains model, model_profile, or hooks. |
agent-invalid-tier | lib/agents.cjs | tier value not in {haiku, sonnet, opus}. |
invalid-tier | lib/model-profiles.cjs | resolve-model was given an invalid tier. |
invalid-profile | lib/model-profiles.cjs | resolve-model was given an invalid model_profile. |
Git / commit
| Code | Source | Meaning |
|---|---|---|
commit-paths-invalid | lib/git.cjs | assertCommittablePaths rejected the input shape. |
commit-all-paths-gitignored | lib/git.cjs | All paths in files_modified are gitignored (hard-fail). |
commit-no-paths | lib/git.cjs | Commit invoked with an empty path list. |
task-commit-not-found | lib/git.cjs | findCommitByTaskId found no matching commit. |
list-task-commits-invalid | lib/git.cjs | listTaskCommits given an empty/invalid prefix. |
State / config
| Code | Source | Meaning |
|---|---|---|
schema-version-mismatch | lib/state.cjs | STATE.md schema version does not match the runtime expectation. |
config-parse-error | bin/np-tools/config.cjs | config.json is not valid JSON. |
config-forbidden-key | bin/np-tools/config.cjs | Dotted key path contains a forbidden segment. |
config-invalid-key | bin/np-tools/config.cjs | Dotted key segment violates /^[a-zA-Z0-9_-]+$/. |
Templates
| Code | Source | Meaning |
|---|---|---|
template-not-found | lib/template.cjs | Template file missing. |
template-unresolved-var | lib/template.cjs | placeholder has no answer key. |
Verify / validate
| Code | Source | Meaning |
|---|---|---|
verify-file-unreadable | lib/verify.cjs | VERIFICATION.md cannot be read at the expected path. |
verify-milestone-dir-missing | lib/verify.cjs | /np:verify-work <N> invoked on a milestone that has no directory yet. |
verify-work-invalid-phase | bin/np-tools/verify-work.cjs | Milestone argument not a positive integer. |
verify-work-not-found | bin/np-tools/verify-work.cjs | Milestone id not in roadmap.yaml. |
verify-work-invalid-sc-id | bin/np-tools/verify-work.cjs | record-sc SC id not of the form SC-<N>. |
verify-work-invalid-status | bin/np-tools/verify-work.cjs | SC status not Pass / Fail / Defer / Pending. |
verify-work-file-unreadable | bin/np-tools/verify-work.cjs | record-sc before emit-draft. |
verify-work-sc-not-found | bin/np-tools/verify-work.cjs | SC id absent from the draft VERIFICATION.md. |
Output-schema enforcement (ADR-0017)
| Code | Source | Meaning |
|---|---|---|
output-schema-violation | lib/output-lint.cjs::enforceFile, bin/np-tools/output-lint.cjs check --enforce, bin/np-tools/doctor.cjs::_checkOutputSchemas | Output artefact failed schema lint. Inspect the violations[] array — re-spawn the producing agent with the diff as feedback. Never hand-edit. |
output-schema-not-found | lib/schemas/index.cjs::getSchema | Unknown schema name passed to output-lint. Run output-lint list to see registered names. |
output-lint-missing-file | bin/np-tools/output-lint.cjs check | --file <path> argument missing or empty. |
output-lint-missing-schema | bin/np-tools/output-lint.cjs prompt | --schema <name> argument missing. |
output-lint-cannot-infer-schema | bin/np-tools/output-lint.cjs check | Filename does not match a known artefact pattern (*-VERIFICATION.md, *-VALIDATION.md, *-RESEARCH.md, spawn-*.md); pass --schema explicitly. |
output-lint-unknown-verb | bin/np-tools/output-lint.cjs | Verb not in `check |
Project lifecycle / archive (ADR-0016)
| Code | Source | Meaning |
|---|---|---|
archive-no-project | lib/archive.cjs::archiveProject | PROJECT.md not present — nothing to archive. |
archive-not-complete | lib/archive.cjs::archiveProject | Project status reports blockers; pass --force (or run /np:close-project first) to archive anyway. Manifest will record forced: true. |
archive-worktrees-present | lib/archive.cjs::archiveProject | .nubos-pilot/worktrees/ is non-empty. Clean up via /np:worktree-list / /np:worktree-remove, or pass --force. |
archive-collision | lib/archive.cjs::archiveProject | More than 99 archives for the same slug + date — should never happen in practice. |
archive-path-escape | lib/archive.cjs::readArchiveFile | Relative path in archive-project read --rel escapes the archive directory. Path-traversal guard. |
archive-invalid-project-status | lib/archive.cjs::setProjectStatus | Value not in {active, completed}. |
archive-read-missing-name | bin/np-tools/archive-project.cjs | read verb without --name <archive-dir>. |
archive-read-missing-rel | bin/np-tools/archive-project.cjs | read verb without --rel <relative-path>. |
archive-project-unknown-verb | bin/np-tools/archive-project.cjs | Verb not in `status |
close-project-unknown-verb | bin/np-tools/close-project.cjs | Verb not in `init |
project-already-initialized | bin/np-tools/new-project.cjs::_apply | PROJECT.md exists and Phase -1 was not taken. Re-run with Phase -1 archive choice or resolve manually. |
Researcher reconciliation (ADR-0018)
| Code | Source | Meaning |
|---|---|---|
researcher-spawn-missing | lib/researcher-reconciler.cjs::parseSpawnOutput | Spawn output file does not exist at the expected path. |
researcher-spawn-frontmatter | lib/researcher-reconciler.cjs::parseSpawnOutput | Spawn output frontmatter unparseable — file likely violates researcher-output schema. |
researcher-reconcile-no-research-dir | lib/researcher-reconciler.cjs::prepareReconcilerInput | No research/ subdir under M<NNN>/. Stage 1 of the swarm did not run. |
researcher-reconcile-no-spawn-files | lib/researcher-reconciler.cjs::prepareReconcilerInput | research/ exists but contains no spawn-*.md files. |
researcher-reconcile-no-final | bin/np-tools/researcher-reconcile.cjs gate | M<NNN>-RESEARCH.md does not exist yet. Reconciler stage did not run or failed schema lint. |
researcher-reconcile-invalid-milestone | bin/np-tools/researcher-reconcile.cjs | Milestone argument not a positive integer. |
researcher-reconcile-missing-file | bin/np-tools/researcher-reconcile.cjs parse-spawn | --file <path> argument missing. |
researcher-reconcile-unknown-verb | bin/np-tools/researcher-reconcile.cjs | Verb not in `parse-spawn |
Undo / recovery
| Code | Source | Meaning |
|---|---|---|
undo-missing-prefix | bin/np-tools/undo.cjs | /np:undo called with no argument. |
undo-invalid-prefix | bin/np-tools/undo.cjs | Prefix not a milestone number or M<NNN>[-S<NNN>]. |
undo-task-missing-id | bin/np-tools/undo-task.cjs | /np:undo-task invoked without a task id. |
undo-task-invalid-id | bin/np-tools/undo-task.cjs | Task id format invalid. |
undo-task-commit-not-found | bin/np-tools/undo-task.cjs | No task(<id>): commit in the repo. |
reset-slice-invalid-task-id | bin/np-tools/reset-slice.cjs | Explicit task id argument malformed. |
reset-slice-no-state | bin/np-tools/reset-slice.cjs | STATE.md not readable — not inside a nubos-pilot project. |
checkpoint-invalid-task | lib/checkpoint.cjs | Checkpoint operation referenced an unknown task. |
checkpoint-invalid-task-id | lib/checkpoint.cjs | Task id format invalid. |
Nubosloop / loop-run-round (ADR-0010)
| Code | Source | Meaning |
|---|---|---|
loop-run-round-invalid-task-id | bin/np-tools/loop-run-round.cjs | First positional argument does not match M<NNN>-S<NNN>-T<NNNN>. |
loop-run-round-missing-phase | bin/np-tools/loop-run-round.cjs | --phase flag missing. |
loop-run-round-invalid-phase | bin/np-tools/loop-run-round.cjs | --phase not in {preflight, post-researcher, post-executor, post-critics, commit, stuck}. |
loop-run-round-preflight-missing-query | bin/np-tools/loop-run-round.cjs | --phase preflight invoked without --query. |
loop-preflight-already-stamped | bin/np-tools/loop-run-round.cjs | --phase preflight re-invoked on a task whose loop has already entered the round-1 body (Gap #9 from the 2026-05-05 review). Pass --force-preflight to override. |
loop-post-researcher-missing-spawn-audit | bin/np-tools/loop-run-round.cjs | --phase post-researcher invoked without swarm.research.k np-researcher audit entries (k-of-k Layer-C gate). |
loop-run-round-post-executor-missing-verify | bin/np-tools/loop-run-round.cjs | --phase post-executor invoked without --verify-exit-code. |
loop-post-executor-missing-spawn-audit | bin/np-tools/loop-run-round.cjs | Layer-C: no executor / build-fixer audit entry for the round. |
loop-run-round-verify-output-traversal | bin/np-tools/loop-run-round.cjs | --verify-output-path resolves outside cwd or TMPDIR. |
loop-run-round-verify-output-unreadable | bin/np-tools/loop-run-round.cjs | --verify-output-path could not be read. |
loop-run-round-post-critics-missing-outputs | bin/np-tools/loop-run-round.cjs | --phase post-critics invoked with neither --critic-outputs nor --critic-outputs-path. |
loop-run-round-post-critics-missing-outputs-invalid-json | bin/np-tools/loop-run-round.cjs | Inline --critic-outputs is not valid JSON. |
loop-run-round-post-critics-invalid-outputs | bin/np-tools/loop-run-round.cjs | --critic-outputs parsed JSON is not an array. |
loop-run-round-post-critics-conflicting-outputs | bin/np-tools/loop-run-round.cjs | (L5) Both --critic-outputs and --critic-outputs-path passed. Pick exactly one. |
loop-run-round-critic-outputs-path-traversal | bin/np-tools/loop-run-round.cjs | (L5) --critic-outputs-path resolves outside cwd or TMPDIR. |
loop-run-round-critic-outputs-path-unreadable | bin/np-tools/loop-run-round.cjs | (L5) --critic-outputs-path cannot be read. |
loop-run-round-critic-outputs-path-invalid-json | bin/np-tools/loop-run-round.cjs | (L5) --critic-outputs-path content is not valid JSON. |
loop-run-round-critic-outputs-path-invalid-shape | bin/np-tools/loop-run-round.cjs | (L5) --critic-outputs-path JSON is neither an object nor an array. |
loop-post-critics-missing-critic-audit | bin/np-tools/loop-run-round.cjs | Layer-C: no np-critic audit entry for the round. Single-Critic Revision — exactly one audit, not three. |
loop-commit-precondition-missing | bin/np-tools/loop-run-round.cjs | Layer-B: --phase commit invoked without prior verify-green AND empty findings array on the checkpoint. Pass --force-commit-phase to override. |
loop-run-round-stuck-conflicting-findings | bin/np-tools/loop-run-round.cjs | (L5) Both --findings and --findings-path passed to --phase stuck. Pick exactly one. |
arg-invalid-json | bin/np-tools/_args.cjs | Generic optional-JSON-flag parse failure. |
Loop tool-use audit
| Code | Source | Meaning |
|---|---|---|
loop-audit-invalid-task-id | bin/np-tools/loop-audit-tool-use.cjs | First positional argument does not match M<NNN>-S<NNN>-T<NNNN>. |
loop-audit-missing-agent | bin/np-tools/loop-audit-tool-use.cjs | Append mode invoked without --agent. |
loop-audit-missing-log | bin/np-tools/loop-audit-tool-use.cjs | --tool-use-log required for an AUDITED_AGENT (Rule 9). |
loop-audit-invalid-log | bin/np-tools/loop-audit-tool-use.cjs | --tool-use-log is not a JSON array. |
loop-audit-agent-is-module | bin/np-tools/loop-audit-tool-use.cjs | --agent resolves to a module file (module: true) — modules cannot be audited as if they were spawnable. |
nubosloop-unknown-route | lib/nubosloop.cjs | A finding's route is not in KNOWN_ROUTING_BUCKETS — typo in ROUTE_TABLE. Fail-loud. |
nubosloop-invalid-task-id | lib/nubosloop.cjs | recordLoopState given an empty / malformed task id. |
nubosloop-preflight-invalid-query | lib/nubosloop.cjs | preflightCacheLookup given an empty / non-string query. |
nubosloop-audit-invalid-task-id | lib/nubosloop.cjs | auditToolUse given a malformed task id. |
nubosloop-audit-invalid-agent | lib/nubosloop.cjs | auditToolUse given an empty / non-string agent name. |
nubosloop-audit-invalid-log | lib/nubosloop.cjs | auditToolUse given a non-array tool-use log. |
nubosloop-auto-log-invalid-task-id | lib/nubosloop.cjs | autoLogLearning task id does not match the required shape. |
Headless subprocess (Cost Layer L6)
Codes raised by spawn-headless — see ADR-0010 §L6.
| Code | Source | Meaning |
|---|---|---|
spawn-headless-missing-agent | bin/np-tools/spawn-headless.cjs | --agent flag missing. |
spawn-headless-invalid-agent-name | bin/np-tools/spawn-headless.cjs | --agent must match /^[a-zA-Z0-9_-]+$/ — defends against path-injection. |
spawn-headless-missing-prompt-path | bin/np-tools/spawn-headless.cjs | --prompt-path flag missing. |
spawn-headless-missing-output-path | bin/np-tools/spawn-headless.cjs | --output-path flag missing. |
spawn-headless-invalid-timeout | bin/np-tools/spawn-headless.cjs | --timeout-ms is non-numeric or below 1000. |
spawn-headless-path-traversal | bin/np-tools/spawn-headless.cjs | --prompt-path or --output-path resolves outside cwd or TMPDIR. |
spawn-headless-agent-not-found | bin/np-tools/spawn-headless.cjs | Agent file not in any of .nubos-pilot/agents/, .claude/agents/, or the package agents/. |
spawn-headless-prompt-unreadable | bin/np-tools/spawn-headless.cjs | --prompt-path could not be read. |
spawn-headless-claude-not-found | bin/np-tools/spawn-headless.cjs | The claude binary (or NUBOS_PILOT_CLAUDE_BIN override) is not on $PATH. |
spawn-headless-spawn-failed | bin/np-tools/spawn-headless.cjs | Generic subprocess spawn failure (other than ENOENT / ETIMEDOUT). |
spawn-headless-timed-out | bin/np-tools/spawn-headless.cjs | Subprocess exceeded --timeout-ms (or spawn.headless.timeout_ms). |
A non-zero subprocess exit (i.e. claude itself ran and returned non-zero) does NOT raise an error. It returns rc=2 with exit_code and stderr_excerpt on the JSON payload, so the caller can decide to fall back to the Agent-tool path (spawn.headless.fallback_on_error).
Plan-milestone / execute-milestone
| Code | Source | Meaning |
|---|---|---|
plan-milestone-invalid-arg | bin/np-tools/plan-milestone.cjs | Milestone argument invalid. |
plan-milestone-not-found | bin/np-tools/plan-milestone.cjs | Milestone not in roadmap.yaml. |
plan-milestone-unknown-verb | bin/np-tools/plan-milestone.cjs | Unknown subcommand verb. |
execute-milestone-invalid-arg | bin/np-tools/execute-milestone.cjs | Milestone argument invalid. |
execute-milestone-not-found | bin/np-tools/execute-milestone.cjs | Milestone not in roadmap.yaml. |
execute-milestone-invalid-task-id | bin/np-tools/execute-milestone.cjs | Task full-id malformed. |
execute-milestone-task-milestone-mismatch | bin/np-tools/execute-milestone.cjs | Task belongs to a different milestone. |
execute-milestone-task-not-found | bin/np-tools/execute-milestone.cjs | Task plan file absent on disk. |
execute-milestone-unknown-verb | bin/np-tools/execute-milestone.cjs | Unknown subcommand verb. |
Install / payload
| Code | Source | Meaning |
|---|---|---|
staging-mkdir-failed | lib/install/staging.cjs | Staging directory could not be created. |
staging-clean-failed | lib/install/staging.cjs | Stale staging cleanup failed. |
staging-swap-failed | lib/install/staging.cjs | Atomic swap from staging into payload failed. |
manifest-build-failed | lib/install/manifest.cjs | Could not enumerate / hash the staged tree. |
manifest-invalid-structure | lib/install/manifest.cjs | Manifest JSON shape is wrong. |
manifest-parse-failed | lib/install/manifest.cjs | Manifest file unreadable / unparseable. |
manifest-write-failed | lib/install/manifest.cjs | Manifest atomic write failed. |
manifest-path-traversal | bin/install.js | Manifest path contains .. or is absolute. |
target-is-symlink | bin/install.js | Refuses to write into a symlinked payload directory. |
backup-source-missing | lib/install/backup.cjs | File to back up does not exist. |
backup-refuses-symlink | lib/install/backup.cjs | Refuses to back up a symlink. |
backup-rename-failed | lib/install/backup.cjs | Backup rename failed. |
agents-md-missing-notice | lib/install/agents-md.cjs | Generated AGENTS.md is missing the managed notice. |
agents-md-invalid-input | lib/install/agents-md.cjs | Bad input to generateAgentsMd. |
codex-toml-invalid-input | lib/install/codex-toml.cjs | Codex config.toml repair input is invalid. |
Workflow-specific
| Code | Source | Meaning |
|---|---|---|
project-already-initialized | bin/np-tools/new-project.cjs | /np:new-project invoked when PROJECT.md already exists. |
project-not-initialized | bin/np-tools/new-milestone.cjs | /np:new-milestone invoked before /np:new-project. |
answers-missing-field | bin/np-tools/{new-project,new-milestone}.cjs | Interview answer file missing a required key. |
answers-not-readable | bin/np-tools/{new-project,new-milestone}.cjs | --apply <answers.json> path unreadable. |
answers-parse-error | bin/np-tools/{new-project,new-milestone}.cjs | Answer file is not valid JSON. |
new-milestone-forbidden-write | bin/np-tools/new-milestone.cjs | Internal defensive guard — should never surface. |
discuss-invalid-phase-arg | bin/np-tools/discuss-phase.cjs | Milestone argument not a positive integer. |
discuss-phase-not-found | bin/np-tools/discuss-phase.cjs | Milestone id not in roadmap.yaml. |
research-invalid-phase-arg | bin/np-tools/research-phase.cjs | Milestone argument not a non-negative integer. |
research-phase-not-found | bin/np-tools/research-phase.cjs | Milestone id not in roadmap.yaml. |
add-tests-invalid-phase | bin/np-tools/add-tests.cjs | Milestone argument not a positive integer. |
add-tests-verification-missing | bin/np-tools/add-tests.cjs | No VERIFICATION.md found — run /np:verify-work <N> first. |
