- Get Started

Worker & Pipeline Issues

For connectivity and auth issues, see Connectivity & Auth. For common failures and diagnostics overview, see the Troubleshooting page.

Worker Timeouts

A worker timeout means a FORGE, SENTINEL, or VESSEL workspace did not finish its assigned step within the configured timeout. Timeouts are usually caused by one of three things: a long LLM call, a hung MCP server, or a workspace that failed to provision.

bash
# Find worker workspace for a ticket
coder ws ls | rg 'forge-1-my-team'

# SSH into it and inspect processes
coder ssh forge-1-my-team
ps aux | rg -i 'claude|codex|aider'

tail -f /tmp/openflows-worker.log

Do not manually kill a healthy worker

A worker may be slow because the LLM is genuinely reasoning through a complex problem. Killing it loses the in-progress context and triggers NEXUS reconcile. Only terminate a worker if it is clearly hung or if the LLM call has exceeded the gateway timeout.

SENTINEL Rejection Loops

A SENTINEL rejection loop occurs when SENTINEL repeatedly rejects a plan or segment and FORGE cannot satisfy the requested changes. This is the most common failure mode in the review phase. It is not a bug in SENTINEL; it is a sign that the specification is ambiguous or the implementation is hitting a genuine quality issue.

NEXUS tracks consecutive rejections for the same segment. After SENTINEL_REJECTION_LIMIT (default 3), the ticket is escalated to AwaitingHuman with a STATUS.json blocker.

bash
# Count rejections for a ticket in the log
rg 'SENTINEL.*REJECTED' /tmp/openflows-controller.log | rg 'ISSUE-123' | wc -l

# Read worker status to see rejection reason
cat /tmp/workspaces/forge-1-my-team/STATUS.json | jq .errors

Merge Conflicts

VESSEL monitors the mergeable field of the PR. If it becomes false, VESSEL retries after a backoff. If it remains false after several retries, the ticket is escalated.

CauseWhat to check
CI failingVESSEL waits for CI to pass. Check PR checks on GitHub and CI provider logs.
Branch protectionGitHub branch protection rules may require reviews or status checks VESSEL cannot satisfy.
Merge conflictBase branch has moved forward. NEXUS will reassign ticket or escalate.
Draft PRVESSEL only merges non-draft PRs. FORGE may have opened PR as draft for manual review.
Unauthorized mergeCoder external auth identity lacks merge permission. Check repository settings.
bash
# Check PR mergeable state via GitHub CLI
gh pr view 123 --repo owner/repo --json mergeable,state,reviewDecision,statusCheckRollup

How to Read STATUS.json

STATUS.json is a worker-written artifact that declares the current state of a ticket. It is written at the end of every significant phase and whenever a worker encounters a blocker. Operators should read it as the worker's own explanation of what happened, not as a system-generated log.

json
{
  "outcome": "blocked",
  "phase": "review",
  "ticket": "ISSUE-123",
  "pr_url": null,
  "blocker": {
    "kind": "AmbiguousRequirement",
    "description": "The ticket asks to 'refactor the parser' but does not specify which parsing rules must be preserved.",
    "files_written": ["PLAN.md", "CONTRACT.md"],
    "question_for_human": "Which edge cases in the current parser must remain unchanged?"
  },
  "errors": ["SENTINEL rejected segment 2: missing error handling for malformed input"],
  "last_updated": "2026-07-20T15:43:21Z"
}
FieldMeaning
outcomeOne of in_progress, completed, failed, blocked, or awaiting_human.
phaseCurrent pipeline phase: planning, implementing, review, pr_opened, merged.
ticketThe issue or ticket ID associated with this status.
pr_urlURL of the opened pull request, if any.
blockerWhen outcome is blocked, object describing blocker kind and question.
errorsArray of recent error messages. Empty when healthy.
last_updatedISO timestamp of the last status write.
Blocker KindMeaning
AmbiguousRequirementTicket description is unclear; NEXUS needs human to refine spec.
DependencyNotMergedCode dependency missing because prerequisite PR not yet merged.
FileLockConflictAnother worker/process is holding a required file or resource.
OtherCatch-all for blockers that do not fit above. Read description.

Blocked is better than wrong

A blocked status is a deliberate human escalation. It means the system recognized it could not safely proceed and stopped. When you see a blocked status, answer the question_for_human in the ticket, update the spec, and resume the tenant. Do not bypass the blocker by editing Redis manually unless you understand the risk.

Escalation Checklist

If the above steps do not resolve the issue, gather the following information before escalating to NEXUS or another team:

Preserve worker workspaces during incidents

By default, worker workspaces are torn down after a ticket is merged. During an incident, set the tenant to isolated mode to prevent teardown, then inspect the workspaces. Once you have the diagnostics you need, resume the tenant and let the normal lifecycle continue.