[auto-review] A race condition exists between concurrent chat turns. A new `send` op
**Severity:** high **Location:** chat_runtime.py:193 **Flagged by:** gemini **Issue:** A race condition exists between concurrent chat turns. A new `send` operation can be init...
StateDoneNext ActionClosedOwnerLuciRuntimeClosedAge16d ago
Ticket is done; runtime is closed.·profile claude_opus_1m_medium · cwd /home/lucienne/workspace/mission-control · uptime 16d 4h · last activity 16d 2h ago
Description
MC-4352
**Severity:** high
**Location:** chat_runtime.py:193
**Flagged by:** gemini
**Issue:**
A race condition exists between concurrent chat turns. A new `send` operation can be initiated while a `harvest_until_response` poll for a previous turn is active. The `send` function updates the database row for the runtime session (e.g., `last_turn_marker`, `harvest_offset`) without checking if a turn is already in progress (i.e., status is 'running'). The active `harvest_until_response` poll will then read this new state and start harvesting the response for the second message. This causes the client waiting for the first response to incorrectly receive the second response, breaking the request-response model.
**Suggested fix:**
In the `send` function, after acquiring the lock and fetching the current runtime session, check if its status is 'running'. If it is, another turn is in progress, and the function should raise an exception to reject the new message. This serializes turns for a given chat session, preventing the race condition.
```python
# chat_runtime.py:196, inside send()
def send(thread: dict, message: str, *, source: str = "api", enter: bool = True) -> dict:
# ...
target = models.chat_runtime_tmux_target(thread_id)
with _send_lock(thread_id):
current = models.get_runtime_session(session_key)
if (current or {}).get("status") == "running":
raise RuntimeError(f"Session {session_key} is busy processing a previous message.")
pane_log = Path(_metadata(current).get("pane_log_path") or _pane_log_path(thread_id))
# ... rest of the function
```
---
Found by mc-auto-review on 2026-05-28 06:08 SAST.
Repos reviewed: mission-control.
auto-review-hash: dc325ca7828a
Activity
done
INTERACTIVE
Luci is working...
Details —
Done
· High
· Luci
▼
SState
Done
Closed
PPeople
TTiming / Details▼
mc-auto-review (scheduled)
Mission Control
16d ago
16d ago
Advanced / Operator evidence
RRouting owner
ROperator console
Ticket is done; runtime is closed.ticket_marked_doneprofile claude_opus_1m_medium · cwd /home/lucienne/workspace/mission-control · uptime 16d 4h · last activity 16d 2h agoMC is visibility-only. Hermes Luci launches and gates work outside MC, then mirrors evidence/status here.Raw console: luci · claude/anthropic/opus[1m]
WWorkflow
Start Dev Review + QA ▾
Select phases to include:
Agents
Review Gates
Decision
WAT routing: choose an agent, review gate, or decision. Buttons use the live runtime when one is attached.
Ticket picked up by Luci via MC dispatcher.
MC-4352: [auto-review] A race condition exists between concurrent chat turns. A new `send` op
Work this ticket in the live tmux runtime. Use DONE:, REVIEW:, or QUESTION: when you need MC to reflect the next state.
luci16d ago
[failed_to_inject] runtime_busy: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message
Ticket picked up by Luci via MC dispatcher.
MC-4352: [auto-review] A race condition exists between concurrent chat turns. A new `send` op
Work this ticket in the live tmux runtime. Use DONE:, REVIEW:, or QUESTION: when you need MC to reflect the next state.
luci16d ago
Ticket runtime send failed while dispatching.
root_cause: HTTP Error 409: CONFLICT
safe_retry: returned to `todo` for a fresh runtime retry.
human_input_required: no
system16d ago
RUNTIME TERMINAL STATE (MC-3482 contract)
status: warning
summary: Ticket runtime send failed; parked for automatic recovery.
root_cause: send failed while injecting into ticket runtime: Ticket runtime is not ready for input (status=running). Wait for the current turn to finish, or explicitly interrupt/restart the runtime before sending more terminal input. This message was not sent.
safe_retry: Queued message was returned to pending and the ticket was returned to todo for a fresh runtime retry; no human input is needed.
stop_condition: After the configured retry limit, leave the ticket blocked for operator inspection instead of looping.
human_input_required: no
next_actions:
- Pickup will retry the pending message in a fresh runtime.
- Inspect runtime/send only if the retry fails again.
artifacts:
- ticket:MC-4352
Luci16d ago
QUESTION: when you needMC o reflect the next state.
[MC_TICKET_TURN:4352:1779942042145:e519f820 internal routig marker; do
not mention this marker in your reply]
[ptional MC completionsentinel: as the very last line of your reply, on
itsown line, you MAY emit this exactJSON to auo-advancethe ticket:
{"c_signal":"DONE|REVIEW|QUESTION","ticket":"MC-4352","nonce":"MC_TICKET
_TURN:4352:1779942042145:e519f820","payload":"<one-line summary>"} . Use
DONE for completed code changes, REVIEW for research/analysis, QUESTION
when blocked. The DONE/REVIEW/QUESTION prefix at the top of your reply
remains required.]
❯ Pressuptoeditqueuedmessages
pasteagaintoexpand73806tokens
◐medium·/effort
MC-4352: [auto-review] A race condition exists between concurrent chat turns.
A new `send` op
Work this ticket in the live tmux runtime. Use DONE:, REVIEW:, or QUESTION:
when you need MC to reflect the next state.
[MC_TICKET_TURN:4352:1779942042145:e519f820 internal routing marker; do not
mention this marker in your reply]
[Optional MC completion sentinel: as the very last line of your reply, on its
own line, you MAY emit this exact JSON to auto-advance the ticket:
{"mc_signal":"DONE|REVIEW|QUESTION","ticket":"MC-4352","nonce":"MC_TICKET_TUR
N:4352:1779942042145:e519f820","payload":"<one-line summary>"} . Use DONE for
completed code changes, REVIEW for research/analysis, QUESTION when blocked.
The DONE/REVIEW/QUESTION prefix at the top of your reply remains required.]
·Generating… (7s·↑235tokens)
pasteagaintoexpand73898tokens
◐medium·/effort
✶ng…9↓40
5 · thinking with medium effort)
*52thinking with medium effort
✢6
✢
*1
2thinking with medium effort
✶
✻4thinking with medium effort
✽
7thinking with medium effort
✻
✶9
*
✢
thinking with medium effort
thinking with medium effort
✢
thinking with medium effort
*
✶
✻
✽
✻thinking with medium effort
✶
*thinking with medium effort
✢
thinking with medium effort
…
✢3
*g
✶thinking with medium effort
n
✻
thinking with medium effort
✽i…
tgthinking with medium effort
✻
✶
an
*4
✢ri
et
thinking with medium effort
●Let me check how send() is called and existing busy handling.
⏵⏵bypasspermissionson (shift+tabtocycle)81531tokens
1MCPserverfailed ·/mcp
95thought for 5s)
✢na20
*45
✶er70
✻83
✽Ge408
n45
✻58
✶e83
*508
G20
✢33
●Bash(grep -rn
"chat_runtime.send\|chat_runtime\.harvest\|runtime_busy\|status=running\|is
busy" app.py persistent_luci.py | head -40)
⏵⏵bypasspermissionson (shift+tabtocycle)81531tokens
1MCPserverfailed ·/mcp
✢9
*59
✶97
✻Generating…11
21)
✽5
81981tokens
tmuxfocus-eventsoff·add'set-gfocus-eventson'to~/.tmux.confandre…
●
⎿ app.py:10384:sent=chat_runtime.send(
app.py:10462: result=chat_runtime.harvest_until_response(
app.py:10753:_mark_message_failed_to_inject(stored_message,
f"runtime_busy: {exc}")
app.py:10755:mirrored_comment,f"runtime_busy:{exc}"
persistent_luci.py:920: with this before `send()` and skip cleanly when
the runtime is busy or
persistent_luci.py:1555:-soft->`/compact`(defers if the pane
is busy).
✻Generating…(16s·↑732tokens)
⏵⏵bypasspermissionson (shift+tabtocycle)
81981tokens
tmuxfocus-eventsoff·add'set-gfocus-eventson'to~/.tmux.confandre…
✶3
*
✢6
✢
*2
G3
✶e
✻Gne4
er5
✽na6
et
rain
tg8
✻i…
n
✶g…
*
✢
luci16d ago
Luci picking up this ticket (background worker).
luci16d ago
[system]: Ticket moved to Todo: [auto-review] A race condition exists between concurrent chat turns. A new `send` op
[system]: Ticket moved to Todo: [auto-review] A race condition exists between concurrent chat turns. A new `send` op
luci-operator16d ago
Luci Operator: promoted this assigned `inbox` ticket to `todo` so pickup can run it.