anthropics / anthropics/claude-code

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

Abierto
#92,789 0 comentarios 0 reacciones 0 asignados Ver en GitHub
area:desktop bug has repro platform:linux
Lenguaje dominante
Python
Estrellas
145k
Forks
23.1k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

# 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"`.
2. The user's next prompt is captured in a `{"type":"last-prompt",
"lastPrompt": "...", ...}` marker in the transcript.
3. **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.
4. 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.
5. 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.
6. 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.
2. Surface *something* in the UI when a queued prompt has not begun
processing after some threshold, distinct from "model is thinking."
3. 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.
4. 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.

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Línea de trabajo

Start at the claude-desktop entry point and inspect the session transcript JSONL around the last-prompt marker, comparing sessions where dispatch succeeds with those that stop growing. Reproduce the queued-prompt hang and trace the backend turn-dispatch path; done means the prompt either starts processing or the UI surfaces a recoverable timeout/error instead of remaining silent.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
linux
Área
backend, desktop, devtools
Tipo de issue
Error
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Activo
Claridad
Bastante claro
Aptitud para principiantes
25/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.