Session hangs indefinitely — queued prompt never dispatched (reproduced 5x, 2 unrelated projects)

Status Open
Reported on v2.1.197
Maintainer reply None cached
Activity 0 comments · opened Sep 8, 2026

Session hangs indefinitely — queued prompt never dispatched (reproduced 5x across 2 unrelated local projects)

TL;DR

A Claude Code session (desktop app) periodically becomes permanently
unresponsive: the next user prompt gets recorded as submitted, but no
UserPromptSubmit hook ever runs, no model turn starts, no error surfaces.
The backend process stays alive — idle, not crashed, not spinning — for
hours until someone manually kills it (SIGTERM). Reconnecting is not a
reliable fix and can re-hang immediately on the next turn. Reproduced 5
times across 2 unrelated local git repositories, one of which has no
custom Claude Code hooks/settings at all
, which rules out
project-specific tooling as the cause.

Environment

  • Claude Code version: 2.1.197
  • Entry point: claude-desktop (desktop app) in every occurrence
  • Model: claude-sonnet-5
  • OS: Linux (Ubuntu-based), local machine
  • Occurrences span two separate, unrelated local git repositories

(different projects), several branches, across 9 days

The pattern

Every occurrence shares this shape, read from the session transcript JSONL:

  1. Some turn completes normally — either a SessionStart hook fires and

completes (matcher compact, resume, or a plain trigger; exitCode:
0
, on the order of 100ms), or a full assistant message ends with
stop_reason: "end_turn".

  1. The user's next prompt is captured in a `{"type":"last-prompt",

"lastPrompt": "...", ...}` marker in the transcript.

  1. Nothing follows. No UserPromptSubmit hook success/error entry, no

assistant message, no tool call, no error. The transcript file simply
stops growing at that point.

  1. The backend OS process for the session is either:
  • still alive, in state S (sleeping), all threads blocked on

futex_do_wait / ep_poll / wait_woken — genuinely idle, not
spinning in a hot loop or retry storm; or

  • not found running at all — the backend appears to have exited on its

own, leaving the desktop UI pointed at a dead session with nothing
left to even kill.

  1. No hook subprocess is ever found alive/stuck in the process tree at

inspection time — only long-lived MCP server child processes (where the
project configures any), themselves idle.

  1. Manually sending SIGTERM to the backend process always terminates it

(and any MCP-server child processes) cleanly within ~2s, no orphans
left behind.

Occurrences (summarized, identifying details omitted)

| # | Repo | Prompt that stalled | Approx. length | What preceded it | Backend process when found | Custom hooks in this project? |
|---|------|----------------------|-----------------|--------------------|------------------------------|---|
| 1 | Project A | short git-push instruction | ~7 chars | SessionStart (compact), completed OK | Alive, idle, ~3h → killed | Yes, extensive |
| 2 | Project A (same session, reconnected after #1) | short git-push instruction (different wording) | ~6 chars | SessionStart (resume), completed OK | Alive, idle, ~13h → killed | Yes, extensive |
| 3 | Project A (same session, next day) | short "open PR, merge" instruction | ~20 chars | one full successful assistant turn, itself preceded by SessionStart (compact) | No process found at all | Yes, extensive |
| 4 | Project A, different branch/worktree | short "merge it" instruction | ~10 chars | SessionStart, completed OK, essentially same millisecond | Alive, idle, ~2h43m → killed | Yes, extensive |
| 5 | Project B (unrelated repo) | a longer, unrelated planning sentence | ~99 chars | a full successful assistant turn (end_turn), then an auto-generated title event | Alive, idle, ~11h → killed | No — this project has no .claude/settings.json at all |

What we ruled out

Project A has an extensive custom hooks setup (SessionStart,
UserPromptSubmit, PreToolUse, PostToolUse, Stop, custom
Node-script hooks). Given the symptom, these were the first suspect for
occurrences 1–4:

  • Occurrences #1, #2, #4 had short prompts that would have been guarded

out before any LLM/network call in this repo's UserPromptSubmit hooks
(an internal length threshold skips network-based classification for
very short prompts). Those hooks cannot be the cause for those three.

  • The other relevant UserPromptSubmit hook is fully wrapped in

try/catch with fail-open semantics and only does local, synchronous
filesystem/git calls (no network) — an unlikely candidate, though it
lacks an explicit subprocess timeout (a latent risk worth hardening
regardless, not confirmed as this bug's cause).

  • No hook process was ever found alive/stuck in the process tree, and no

stale git lock existed, at any of the 5 inspections.

Occurrence #5 is the decisive one: it happened in a completely
different, unrelated project with zero custom Claude Code
configuration
— no hooks, no skills, nothing beyond stock Claude Code.
It shows the exact same signature (turn completes → next prompt captured
→ dead silence, idle backend process) as the occurrences in the
heavily-instrumented project, on a long prompt this time (so any
length-based hook guard is irrelevant anyway — there are no hooks at all
in that project). This strongly indicates the bug is in Claude Code / the
claude-desktop entrypoint itself, not in any project-specific tooling.

Impact

  • Every occurrence made the session completely unusable: no response, no

error, no visible indication of failure, no automatic recovery — until a
human manually found and killed the OS process from a terminal.

  • The desktop app's UI gave no indication in any case that the backend had

stopped making progress (no error, timeout, or retry surfaced).

  • Reconnecting after killing the process is not a reliable fix.

Occurrence #2 re-hung on the very next turn immediately after
reconnecting from #1. Occurrence #3 hung again the following day on the
same session. This is a recurring, not one-off, failure mode for
long-lived sessions.

  • Diagnosing and recovering each occurrence required manual ps/kill

work outside the Claude Code UI — not something a typical user could do
unassisted.

Suggested follow-ups

  1. A client-side timeout/watchdog on the turn-dispatch path, so a stalled

request surfaces as a visible error/retry instead of an indefinite
silent hang. This should apply broadly, not just right after
SessionStart — occurrence #5 stalled after an ordinary completed turn
with no hooks involved at all.

  1. Surface something in the UI when a queued prompt has not begun

processing after some threshold, distinct from "model is thinking."

  1. Investigate whether some piece of persisted per-session state (written

around turn completion / SessionStart / the queued-prompt handoff)
can itself get wedged and carry over across backend process restarts —
occurrence #2 re-hung immediately after a fresh process reconnected to
the same session id, which points at state rather than a purely
in-process condition.

  1. Happy to share full session JSONL transcripts privately if that would

help narrow this down — didn't want to paste raw transcripts (with
internal file/branch names) into a public issue.

Reproduction

Reproduced 5 times, 2 unrelated local projects, several branches, spanning
9 days. No special action was needed to trigger it beyond normal usage
(editing, discussing next steps, running CI) — it appears to be a
low-frequency but real intermittent hang in long-lived claude-desktop
sessions.

View original on GitHub ↗