Skip to content

Troubleshooting

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.

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.

Terminal window
claude login # for Claude Code
codex login # for Codex
# OpenCode / Antigravity / Hermes: see each tool's docs

Why: 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.

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.

Terminal window
export JUNE_LINEAR_WEBHOOK_SECRET=lws_
npm start

Why: 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.

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.

Terminal window
# new URL
ngrok http 8787
# Linear: Settings → API → Webhooks → edit your webhook → paste new URL

Why: the free ngrok tier rotates the URL on every restart. Cloudflare Tunnel gives you a stable hostname for free — see Setup.

Symptom: spawn errors like Error: spawn claude ENOENT.

Fix: install the runner or set the binary path env var.

Terminal window
which claude # should print a path
export LINEAR_CLAUDE_BIN=/full/path/to/claude # if needed

Why: 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.

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.

Terminal window
export LINEAR_CLAUDE_TIMEOUT_MS=7200000 # 2 hours

Fix (option 2): disable the timeout entirely (the default).

Terminal window
unset LINEAR_CLAUDE_TIMEOUT_MS

Why: 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.

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.

Terminal window
# verify the key's identity
curl -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.

Symptom: a run finished long ago but the issue never moved to Ready for Review.

Fix: reconcile via the admin endpoint.

Terminal window
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.

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:

Terminal window
export LINEAR_AGENT_COMMENT_MAX_AUTO_FLUSHES=10

Why: 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.

Symptom: nothing in logs/agent.log.

Fix: make sure the log directory is writable, and that you’re tailing the right file.

Terminal window
tail -F logs/agent.log
# or, if you've overridden the path:
tail -F $JUNE_LOG_PATH

Why: 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/.