Hmbown / Hmbown/Codewhale

Engine silently freezes mid-run: user messages are persisted but never answered; no error, no log line, no crash entry

Open
#6,184 5 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Rust
Stars
41k
Forks
3.6k
Avg merge
13h 59m
Merged PRs (30d)
299

Description

## Body

```markdown
### Environment

- codewhale 0.9.13 (Rust TUI), linux x86_64
- provider: zai, model: GLM-5.3-Flash
- posture: Ask / workspace-write

### Summary

During long, tool-heavy runs the engine stops producing model output mid-turn.
Everything the user types afterwards is persisted into the session journal but
never answered. The stall is completely silent: no ERROR/WARN in the TUI log,
no crash entry, the spinner just keeps absorbing input.

This happened twice in two independent sessions on consecutive days.

### Steps to reproduce (observed, not deterministic)

1. Run an interactive session with a long skill-driven task that issues many
bash tool calls (session A), or a multi-turn task with tool approval
round-trips (session B).
2. Mid-run, the model stops emitting output (session B stalled right after an
assistant thinking block, before any text/tool output).
3. Send follow-up user messages. They are accepted and persisted.
4. No reply ever arrives; force-quit is the only way out.

### Observed evidence (timestamps UTC)

Session A `a69916b2…` (2026-09-14):

- TUI log `tui-2026-09-14-2784622.log` ends at `10:51:38` with
`engine.turn completion settled status=Completed delivered=true`.
- The session demonstrably continued for hours after that line and stalled
later. The entire stall window produced **zero** additional log lines —
the freeze is invisible to the log.
- Journal tail contains three consecutive `user` entries with no assistant
response after them (a Chinese follow-up question, `"hello?"`, and a
`/feedback bug` draft request).
- On-disk session JSON is structurally intact: 95 journal entries, valid
`leaf_id` pointing at an existing entry, undamaged parent chain.

Session B `53b16822…` (2026-09-15):

- Assistant emitted a thinking block, then stalled before any text or tool
output. A later `"继续"` (continue) user message also got no response.
- On force-quit, the TUI logged **two** pending turns at the same moment:

```
2026-09-15T03:27:48.318072Z INFO engine.turn: engine turn completion settled status=Interrupted delivered=true
2026-09-15T03:27:48.548725Z INFO engine.turn: engine turn completion settled status=Interrupted delivered=true
```

Note `delivered=true` even though the user received no model output for
either turn — the flag does not mean the user saw anything.

- `~/.codewhale/crashes/` is empty in both cases.

### Expected

- A stalled provider stream should be subject to a read/response timeout and
surface a visible error in the UI.
- Queued user messages during a stalled turn should be rejected or reported,
not silently absorbed.
- `delivered=true` on an Interrupted turn should not be recorded when nothing
was ever rendered to the user.

### Impact

Long tasks can absorb follow-up messages indefinitely with zero feedback. The
user cannot distinguish "still working" from "dead" and must force-quit, which
then triggers the separate resume bug (filed separately).

### Hypothesis (unconfirmed)

No network-layer logs are available, so the transport-side root cause is
unknown. Suspected: a zai streaming hang with no read timeout in the harness.
Regardless of the transport cause, the missing stall detection and the silent
absorption of user messages are harness-side gaps.

---
Sanitized log excerpts: see `attachment-issue-1-logs.en.md`.
```

[attachment-issue-1-logs.en.md](https://github.com/user-attachments/files/32222431/attachment-issue-1-logs.en.md)

Contributor guide

Open the contributing guide

Research direction

Start with the engine.turn completion handling and provider-stream/harness path, using attachment-issue-1-logs.en.md and the TUI log excerpts as evidence. Trace how stalled turns and queued user messages are represented in the session journal. Done means a stalled stream produces a visible timeout or error, queued messages are not silently absorbed, and delivered=true reflects output actually shown to the user.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.