Skip to content
Errors

Errors

Every error Sortie produces falls into one of six categories: startup failures, tracker errors, agent errors, workspace errors, worker exit outcomes, and HTTP API errors. This page documents each: what it means, whether Sortie retries it, and what you should do.

Error kind strings appear in logs exactly as shown below. Search this page for the string you see in your output. For step-by-step diagnosis of the most common failures, see How to troubleshoot common failures.


Startup and configuration errors

These errors prevent Sortie from starting. They appear immediately on launch and cause exit code 1. None are retryable. Sortie exits. Fix the configuration and restart.

CheckLog outputAction
workflow_loadworkflow file cannot be loaded: <details>Provide the correct path as argument, or create ./WORKFLOW.md. If the file exists, fix YAML front matter syntax.
tracker.kindtracker.kind is requiredAdd tracker.kind to your WORKFLOW.md front matter.
tracker_adapterunknown tracker adapter kind "<kind>"; registered: [<list>]Set tracker.kind to one of the kinds the message lists.
tracker.api_keytracker.api_key is required for tracker kind "<kind>" (value may be empty after environment variable expansion)Set the environment variable referenced by tracker.api_key (e.g., $SORTIE_JIRA_API_KEY).
tracker.projecttracker.project is required for tracker kind "<kind>"Add the project field to the tracker section.
tracker.project.formattracker.project must be in owner/repo format (e.g. "sortie-ai/sortie")Use owner/repo format with exactly one / and no whitespace in either segment. Raised by the github and gitea adapters; gitlab validates its project field separately.
agent.kindagent.kind is requiredAdd agent.kind to your WORKFLOW.md front matter.
agent_adapterunknown agent adapter kind "<kind>"; registered: [<list>]Set agent.kind to one of the kinds the message lists.
agent.commandagent.command is required for agent kind "<kind>"Set agent.command or install the agent binary so it’s in PATH.
agent.turn_timeout_msconfig: agent.turn_timeout_ms: must be greater than 0Set agent.turn_timeout_ms to a positive number of milliseconds, or remove the field to use the default.
config.<field> (e.g. config.polling.interval_ms, config.agent.turn_timeout_ms)config: <field>: value is outside the range an integer setting accepts, -9223372036854775808 to 9223372036854775807, with (from SORTIE_<VAR>) appended when the value came from a SORTIE_* overrideSet the field, or the environment variable, to a value within the range. The field’s own value checks still apply once the value is in range.
reactions.<kind> (review_comments, bot_review, auto_merge, merge_conflicts, merge_completion)invalid <field>: value is outside the range an integer setting accepts, -9223372036854775808 to 9223372036854775807, where <field> is poll_interval_ms for any of the five kinds, debounce_ms for review_comments only, watch_window_ms for review_comments, bot_review, auto_merge, or merge_conflicts, and max_continuation_turns for review_comments or bot_reviewSet the named kind’s field to a value within the range. See the reactions reference for when a reaction-configuration change takes effect.
reactions.ci_failure.watch_window_msconfig: reactions.ci_failure.watch_window_ms: must be non-negative, got <val> / config: reactions.ci_failure.watch_window_ms: must not exceed 9223372036854 (about 292 years); use 0 for no time limit, got <val>Set watch_window_ms to a non-negative number of milliseconds no greater than 9223372036854, or 0 to remove the bound.
reactions.<kind> (review_comments, bot_review, merge_conflicts, auto_merge)watch_window_ms must be non-negative, got <val> / watch_window_ms must not exceed 9223372036854 (about 292 years); use 0 for no time limit, got <val>Same fix as above, applied to the named kind’s watch_window_ms. Unlike the ci_failure row, this diagnostic carries no config: prefix and no field path; sortie validate reports it under the check name reactions.<kind>.
tracker.handoff_statetracker.handoff_state: "<val>" collides with active state "<state>" / collides with terminal state "<state>"Use a state that appears in neither active_states nor terminal_states. A handoff parks the issue for a person, so it is neither dispatchable nor terminal. Applies to every tracker.kind.
tracker.no_change_statetracker.no_change_state: requires tracker.handoff_state; a declared run performs no transition where no handoff path applies / tracker.no_change_state: "<val>" must equal tracker.handoff_state or name a member of tracker.terminal_statesSet tracker.handoff_state before setting no_change_state, and give no_change_state the same value as handoff_state or a value listed in terminal_states. See state machine reference.
tracker.handoff_evidencetracker.handoff_evidence: must be one of observed, strict, or offSet the field to observed, strict, or off, or leave it unset for the default observed.
tracker.in_progress_statetracker.in_progress_state: "<val>" is not in active_states / collides with terminal state / collides with handoff_statein_progress_state must be in active_states, must not be in terminal_states, and must not equal handoff_state.
tracker.commentstracker.comments: expected map, got <type>The comments value must be a YAML map, not a scalar or list.
tracker.comments.on_dispatchtracker.comments.on_dispatch: expected bool, got <type>Use true or false. Quoted strings like "true" are not accepted. Same applies to on_completion and on_failure.
codex.approval_policy.interactivecodex.approval_policy is set to a value that lets the agent stop and ask for approval, and an unattended run has no one to answer; only "never" is supportedSet codex.approval_policy: never, or remove the field. See Codex validate-time checks.
claude-code.permission_mode.interactiveclaude-code.permission_mode is set to a value that lets the agent stop and ask for approval, and an unattended run has no one to answer; only "bypassPermissions" is supportedSet claude-code.permission_mode: bypassPermissions, or remove the field. See Claude Code validate-time checks.
dispatch.agent.missing_block<selector> selects agent kind "<kind>", but the workflow front matter carries no "<kind>" settings block; add a top-level "<kind>:" block for that kind, or write "<kind>: {}"Add a top-level block for the named kind. <kind>: {} or a bare <kind>: key is enough. Fires only when dispatch.default.agent or a dispatch.rules[i].agent names a registered kind that differs from the top-level agent.kind; an unregistered kind is reported separately as agent_adapter, and agent.kind itself is never covered.
agent.kind.session_resume<kind>.<key> stops this agent kind from resuming a session across separate agent launches, but Sortie re-dispatches an issue with its earlier session after a retry, a continuation, a stall, or a restart, and every such turn fails. Change <kind>.<key>, or use an agent kind that can resume a session.Change the named key, or select an agent kind that resumes sessions. claude-code.session_persistence: false is the only value any built-in adapter declares this way; remove it or set it to true. See Claude Code validate-time checks.
kiro.trust_tools.untrustedtrust_all_tools does not resolve to true, ...Set kiro.trust_all_tools: true, or leave both trust_all_tools and trust_tools unset, and run the agent inside a hardened sandbox. See Kiro validate-time checks.

Preflight validation reports all failures at once in a single dispatch preflight failed: ... line.

The sortie validate subcommand runs these same checks without starting the orchestrator, and additionally emits advisory warnings for front matter issues (unknown keys, sub-keys, type mismatches), template problems (dot-context misuse in {{ range }}/{{ with }}, unknown variables, unknown sub-fields), and a configuration value that cannot reach the agent it is written for. Use it in CI pipelines or pre-commit hooks to catch configuration errors, typos, and template mistakes before deployment.


Tracker errors

Errors from tracker adapter API calls. They appear in logs with the format tracker: <kind>: <message>.

Three are configuration errors (before any API calls). Six occur at runtime during polling, state transitions, or issue fetches.

Configuration errors

Error kindDescriptionRetryableOperator action
unsupported_tracker_kindThe tracker.kind value has no registered adapter.NoSet tracker.kind to a registered kind. The startup error names every kind the binary registers.
missing_tracker_api_keyThe tracker.api_key field resolved to empty after environment variable expansion.NoSet the environment variable (e.g., SORTIE_JIRA_API_KEY).
missing_tracker_projectThe tracker.project field is absent and the adapter requires it.NoAdd project to the tracker section in WORKFLOW.md.

Runtime errors

Error kindDescriptionRetryableBackoffOperator action
tracker_transport_errorNetwork or connection failure (DNS, TCP timeout, TLS).YesExponentialCheck network connectivity to the tracker endpoint.
tracker_auth_errorAuthentication or authorization failure (HTTP 401/403).No-Verify API key or token and check account permissions.
tracker_api_errorNon-200 HTTP response from the tracker, including rate limiting and 5xx server errors.YesExponentialCheck tracker service status. Usually self-resolves; investigate if persistent.
tracker_not_foundThe requested resource does not exist (HTTP 404).No-Verify the project key and issue identifiers in your configuration.
tracker_payload_errorMalformed or unexpected response body from the tracker.No-Check tracker API version compatibility.
tracker_missing_end_cursorPagination integrity error: expected cursor missing from response.YesExponentialUsually transient. If persistent, report a bug.

Agent errors

Errors from agent adapter sessions. They appear in logs with the format agent: <kind>: <message>.

Error kindDescriptionRetryableBackoffOperator action
agent_not_foundAgent command or binary not found in PATH. Also triggered by SSH exit code 127 (remote binary missing).No-Install the agent binary, or set agent.command in WORKFLOW.md. For SSH workers, install the agent on the remote host.
invalid_workspace_cwdWorkspace path is invalid, doesn’t exist, or isn’t a directory.No-Check workspace.root permissions and available disk space.
response_timeoutStartup or synchronous communication timed out before the agent responded.YesExponentialIncrease agent.read_timeout_ms if persistent.
turn_timeoutA turn, including a self-review turn, exceeded the configured agent.turn_timeout_ms.YesExponentialIncrease the timeout, or simplify the task so the agent finishes faster.
port_exitAgent subprocess exited unexpectedly (non-zero exit code, pipe failure, or crash), or the runtime reported no turn outcome and the adapter had no per-turn process exit to observe.YesExponentialCheck agent logs for crash details. For SSH workers, exit code 255 indicates an SSH connection failure. Check connectivity and verify the host is in worker.ssh_hosts.
response_errorAgent returned a protocol-level error response.YesExponentialCheck agent version compatibility with Sortie.
turn_failedAgent turn completed with a failure status (the agent reported its own failure), or the agent exited with code 0 without reporting a turn outcome and without producing evidence that the model did any work this turn.YesExponentialReview the agent output in Sortie’s logs for failure details. For no-output failures, check WARN-level logs for the agent’s stderr content. Common causes include MCP config parse errors and missing model configuration.
turn_cancelledTurn was cancelled (reconciliation kill, stall detection, the agent.max_tokens in-flight check, or shutdown). The adapter sees one cancellation signal in every case and cannot tell them apart; the run’s recorded status can.No-Expected during reconciliation. No action needed unless frequent outside of shutdown. A run recorded budget_stopped was the token ceiling, not reconciliation.
turn_refusedThe runtime declined to continue the turn and reported so through its own protocol; everything from the declined point onward is excluded from what a later attempt sees, so a retry resumes a different conversation rather than the same one. Reported by the Agent Client Protocol adapter.No-Sortie releases the claim rather than scheduling a retry. Read the run’s own output for what the runtime declined and why; narrow the task or the prompt so the same input does not draw the same refusal.
turn_token_limitThe runtime ended the turn because it hit a token limit of its own, so the same input is expected to hit it again. Reported by the Agent Client Protocol adapter.No-Shorten the prompt or the task, or split the work across more turns.
turn_request_limitThe runtime ended the turn because its own request or turn budget within the session was exhausted. Reported by the Agent Client Protocol adapter.YesExponentialA fresh turn starts a new budget on the runtime’s side; if this recurs, the task likely needs more turns than the runtime allows per session.
turn_outcome_unknownThe runtime ended the turn reporting an outcome this client could not interpret: an unrecognized stop reason, a cancelled outcome neither side asked for, or a line exceeding the connection’s own bound. Reported by the Agent Client Protocol adapter.No-Sortie releases the claim rather than scheduling a retry. Check the agent’s own logs for what it reported; this is the runtime producing something the adapter does not yet recognize, not necessarily a failed turn.
turn_input_requiredThe agent asked for a decision only a person could give: a genuine question, or a permission the adapter had no way to refuse and let the turn continue. Sortie refuses rather than answering on a person’s behalf, and ends the attempt instead of waiting. The claim is released, and the run is recorded with status needs_person rather than failed.No-Read the notification event that precedes it: it names what the agent asked for. Then either satisfy the request outside the run (widen the sandbox, supply the missing decision in the issue or the prompt template) or narrow the task so the agent does not need it. Reconfiguring the agent does not remove this ending; every runtime is already launched non-interactively.
turn_incompleteThe runtime ended the turn with a clean exit but without the task-completion report its own protocol defines, so the turn stopped short of the work it was given. Reported by the Copilot CLI adapter when --max-autopilot-continues is reached before a session.task_complete event arrives; no other built-in adapter reports it today.YesExponentialRaise copilot-cli.max_autopilot_continues if the task needs more autopilot steps per turn. The retry resumes the same session with a fresh continuation ceiling.

Failure text is uniform across coding agents. A turn that exits 0 having produced nothing reports agent exited without producing output, followed by the signals the adapter looked for and did not find. An adapter that reads both model-authored content and tool-call activity reports agent exited without producing output: no message from the agent and no tool call, which covers claude-code, copilot-cli, and opencode. kiro reads only the first, so it reports agent exited without producing output: no message from the agent. A non-zero exit reports exit code N. A runtime that reported no turn outcome and gave the adapter no process exit to observe reports runtime reported no turn outcome. A runtime whose protocol defines a task-completion report, but that ended the turn without one, reports agent stopped without reporting the task complete.


Workspace errors

Errors during workspace preparation, hook execution, and the control-file writes that follow.

Path errors

Format: workspace <op>: <details>

Occur when Sortie prepares the per-issue workspace directory.

OperationMeaningOperator action
sanitizeIssue identifier contains characters invalid for a directory name.Check that your tracker returns clean identifiers.
resolveWorkspace root path resolution failed (e.g., ~ expansion).Verify workspace.root is a valid, absolute-resolvable path.
containmentThe computed workspace path escapes the workspace root. This is a security violation. An identifier like ../../etc was used.Investigate the issue identifier in your tracker. This should not happen with legitimate data.
createDirectory creation failed (permission denied, disk full).Check filesystem permissions and available disk space on workspace.root.
statFilesystem stat failed on the workspace path.Check that the path exists and is accessible.
conflictDirectory already exists when Sortie expected to create a fresh workspace.A previous run may not have cleaned up. Remove the conflicting directory manually, or check before_remove hook behavior.

Hook errors

Format: hook <op>: <details>

Occur when lifecycle hook scripts (after_create, before_run, after_run, before_remove) execute.

OperationMeaningOperator action
validateEmpty script body or invalid timeout (non-positive hooks.timeout_ms).Fix your hook script or set a valid hooks.timeout_ms.
startFailed to spawn the hook subprocess (missing shell, permission denied).On POSIX, check that /bin/sh exists and is executable. On Windows, check that cmd.exe is available.
runScript exited with non-zero exit code. The failure WARN record carries the script’s combined stdout and stderr under hook_output (the last 8 KiB).Read hook_output on the WARN record to diagnose the script failure.
timeoutScript exceeded hooks.timeout_ms, or the run it belongs to was cancelled while the script was executing.Increase hooks.timeout_ms, or make the hook script faster.

Hook errors in after_create prevent the worker from starting. The error is retryable. Hook errors in before_remove are logged but ignored; workspace cleanup still proceeds.

Control-file errors

Format: mcp config generation: <details>

Occur while the worker writes the MCP tool-server configuration (.sortie/mcp.json and .sortie/.gitignore), after the workspace is ready but before the agent session starts.

DetailMeaningOperator action
.sortie is a symbolic link, refusing to write.sortie in the workspace is a symbolic link rather than an ordinary directory. Sortie refuses to write through it.Find and remove whatever replaced .sortie with a symlink (a hook script, a prior agent action), then retry.
.sortie is not a directory.sortie exists as a regular file, not a directory.Remove the file so Sortie can create .sortie as a directory.

This error is retryable with exponential backoff. A run blocked this way never reaches the agent session, and keeps retrying until whatever replaced .sortie is fixed.


Worker exit kinds

Not errors per se, but essential for understanding session outcomes. Appear in logs as worker exiting exit_kind=<kind>.

Exit kindMeaningWhat happens next
normalTurn loop completed without error.If the tracker reports the issue in a terminal state: handoff suppressed, claim released. If handoff_state configured and issue still active: transition attempt, claim released on success, continuation retry on failure. If issue still active with no handoff state configured: continuation retry (1s delay). If issue no longer active: claim released. A .sortie/status soft stop suppresses the continuation retry in every case; blocked also suppresses the handoff transition and, where the dispatch drives issue state, parks the issue with the escalation label and holds it out of dispatch. A run whose handoff-evidence verdict withholds the handoff makes no tracker write; Sortie reads the issue state once more before recording that outcome, and unless that read reports a terminal state the run is recorded as failed rather than succeeded and takes exponential backoff instead of the one-second continuation retry. A terminal result there gives the terminal outcome above instead: handoff suppressed, claim released, no failure record and no retry. A no-change-needed declaration that stood through self-review is exempt from that verdict entirely (it always counts as work observed) and targets tracker.no_change_state instead of handoff_state where that field is set; see declaring that nothing needed changing.
errorFatal error during session.If the error is retryable: exponential backoff retry. If not: claim released immediately, the issue becomes re-dispatchable on the next poll cycle.
cancelledCancelled (reconciliation kill, stall detection, the agent.max_tokens in-flight check, or shutdown).Claim released unless reconciliation pre-scheduled a retry. No automatic retry: reconciliation handles re-dispatch. The run is recorded cancelled, except for a token-ceiling cancel, which is recorded budget_stopped with the tokens used and the ceiling in its error text.

SSH worker errors

When extensions.worker.ssh_hosts is configured, two exit codes carry special meaning.

Exit codeError kindMeaningRetryableOperator action
255port_exitSSH connection failure (refused, timeout, host unreachable).Yes (exponential)Check SSH connectivity. Verify host is in worker.ssh_hosts. Retry prefers the same host but falls back to the least-loaded alternative.
127agent_not_foundRemote agent binary not found in PATH.NoInstall the agent on the remote host. Verify PATH for the SSH user.

HTTP API errors

The JSON API returns errors in a standard envelope:

{
  "error": {
    "code": "issue_not_found",
    "message": "issue identifier \"FOO-999\" not found in current state"
  }
}
CodeHTTP statusMeaning
issue_not_found404Issue identifier not present in current runtime state (not running, not retrying, not budget-exhausted).
snapshot_unavailable503Orchestrator state snapshot temporarily unavailable. Retry after a short delay.
method_not_allowed405Wrong HTTP method for the endpoint (e.g., POST to a GET-only route). The Allow header indicates the correct method.
internal_error500Server-side JSON encoding failure or unexpected error.

For full endpoint documentation, request/response shapes, and curl examples, see HTTP API reference.


Retry behavior

Exponential backoff applies to retryable errors. The next attempt is scheduled with:

delay = min(10000ms × 2^(attempt-1), max_retry_backoff_ms)

With the default max_retry_backoff_ms of 300,000 (5 minutes), the progression is: 10s → 20s → 40s → 80s → 160s → 300s → 300s → …

Non-retryable errors release the claim immediately. The issue becomes dispatchable again on the next poll cycle if it’s still in an active tracker state.

Continuation retries fire after a normal worker exit when max_turns was reached but the issue remains active. These use a fixed 1-second delay with no exponential backoff.

The backoff cap is configurable via agent.max_retry_backoff_ms in WORKFLOW.md.

Was this page helpful?