Troubleshooting
Stuck in Backlog
Section titled “Stuck in Backlog”Symptom: nothing happens when you create or comment on an issue.
Fix: move the issue out of Backlog (Todo, In Progress, anything but Backlog) and re-trigger.
Linear UI: drag the issue from Backlog to Todo.Why: June hard-ignores Backlog. The orchestrator short-circuits right after the webhook fetch — no DB write, no run, no state change. This is intentional: Backlog is for triage, not for live agent work. The Backlog skip happens before any other state evaluation, so even a fresh comment on a Backlog issue won’t engage the agent.
Runner auth missing
Section titled “Runner auth missing”Symptom: the issue moves to In Progress, then immediately to Blocked with an exit-1 error mentioning auth or “not logged in”.
Fix: log in to the runner CLI on the host machine.
claude login # for Claude Codecodex login # for Codex# OpenCode / Antigravity / Hermes: see each tool's docsWhy: June scrubs ANTHROPIC_API_KEY from the Claude child process by design — the runner must use its own login session, not a stray env var. If claude login was never run on this host (or the session expired), the spawn fails.
Webhook signature mismatch
Section titled “Webhook signature mismatch”Symptom: every webhook returns 401; logs show “HMAC mismatch”.
Fix: copy the signing secret from Linear (Settings → API → Webhooks → your webhook) and update JUNE_LINEAR_WEBHOOK_SECRET. Restart.
export JUNE_LINEAR_WEBHOOK_SECRET=lws_…npm startWhy: the secret in Linear and the env var on the host must match exactly. Trailing whitespace counts. If you rotated the secret in Linear, the host is now using a stale value.
ngrok URL changed
Section titled “ngrok URL changed”Symptom: webhooks worked yesterday; today they don’t arrive at all.
Fix: get the new ngrok URL and update the webhook in Linear, OR switch to Cloudflare Tunnel for a stable URL.
# new URLngrok http 8787# Linear: Settings → API → Webhooks → edit your webhook → paste new URLWhy: the free ngrok tier rotates the URL on every restart. Cloudflare Tunnel gives you a stable hostname for free — see Setup.
Runner binary missing
Section titled “Runner binary missing”Symptom: spawn errors like Error: spawn claude ENOENT.
Fix: install the runner or set the binary path env var.
which claude # should print a pathexport LINEAR_CLAUDE_BIN=/full/path/to/claude # if neededWhy: June resolves the runner via PATH by default. If the binary isn’t on the orchestrator’s PATH (often a problem when the service runs under launchd with a stripped env), set the explicit path.
Run times out mid-task
Section titled “Run times out mid-task”Symptom: the runner SIGTERMs midway through a long task; issue moves to Ready for Review or Blocked with a triage summary.
Fix (option 1): bump the timeout.
export LINEAR_CLAUDE_TIMEOUT_MS=7200000 # 2 hoursFix (option 2): disable the timeout entirely (the default).
unset LINEAR_CLAUDE_TIMEOUT_MSWhy: LINEAR_CLAUDE_TIMEOUT_MS=0 (default) disables the hard timeout. The progress comments system already streams visibility, so the kill is opt-in. If you do set a positive value and hit it, the triage pass decides RESUMABLE vs BLOCKED — RESUMABLE issues can be woken by a fresh human comment.
Bot replying to itself
Section titled “Bot replying to itself”Symptom: the agent posts a comment, immediately spawns again, repeats.
Fix: this shouldn’t happen — the orchestrator filters its own bot comments. If it is happening, check that the Linear user the API key is scoped to matches the user posting the comments. A mismatch means the orchestrator doesn’t recognize its own output.
# verify the key's identitycurl -sS -X POST https://api.linear.app/graphql \ -H "Authorization: $JUNE_LINEAR_API_KEY" \ -H 'Content-Type: application/json' \ --data '{"query":"query{viewer{id name email}}"}'Why: self-filter looks at comment.user.id and matches against the API key’s viewer id. If you swap the key mid-run, an in-flight comment can slip through before the new viewer id is cached.
Issue stuck in In Progress
Section titled “Issue stuck in In Progress”Symptom: a run finished long ago but the issue never moved to Ready for Review.
Fix: reconcile via the admin endpoint.
curl -sS -X POST https://your-host/admin/reconcile \ -H "Authorization: Bearer $LINEAR_CLAUDE_ADMIN_TOKEN"Why: if the orchestrator was killed mid-run (host crash, abrupt restart), the running DB row was never closed out. Reconcile marks those rows orphaned, posts a blocker comment, and moves the issues to Blocked. A subsequent human comment will wake them.
Steering caps out
Section titled “Steering caps out”Symptom: rapid back-to-back comments stop steering after a few; the run finishes the in-flight turn before picking up the new comment.
Fix: this is by design. Wait for the run to finish, then comment again. To raise the cap:
export LINEAR_AGENT_COMMENT_MAX_AUTO_FLUSHES=10Why: consecutive steer-flushes are capped at LINEAR_AGENT_COMMENT_MAX_AUTO_FLUSHES (default 5) to prevent an infinite SIGTERM loop on a noisy thread. Once the cap is reached, the orchestrator lets the current turn finish.
Logs aren’t streaming
Section titled “Logs aren’t streaming”Symptom: nothing in logs/agent.log.
Fix: make sure the log directory is writable, and that you’re tailing the right file.
tail -F logs/agent.log# or, if you've overridden the path:tail -F $JUNE_LOG_PATHWhy: June writes to stdout AND logs/agent.log. If the log dir is missing or read-only, only stdout works. Running under launchd or systemd? Make sure the service has write access to logs/.
Where to ask for help
Section titled “Where to ask for help”- GitHub issues for bugs and feature requests.
- GitHub discussions for setup questions and architectural debate.