xai-org/grok-build · error · ToolError
User question session ended unexpectedly (client may have di
Error message
User question session ended unexpectedly (client may have disconnected)
What it means
The ask_user_question tool sends a questionnaire to the client via a channel and blocks on a tokio oneshot receiver for the answers. This error is returned when the oneshot sender was dropped without ever sending a response (`RecvError`), meaning the session that was supposed to answer the question went away. The library throws it because the tool cannot produce a meaningful result once the answering side is gone.
Source
Thrown at crates/codegen/xai-grok-tools/src/implementations/grok_build/ask_user_question/mod.rs:465
question_count,
timeout_secs = ?wait.map(|d| d.as_secs()),
"Asked user questions, blocking for response"
);
// ── Step 6: Block on the oneshot result (whole batch, one timer) ─
// A single pending-decision timeout covers the questionnaire, not per
// question: N questions in one call share one wait.
// A `None` budget (`timeout_enabled = false`) runs the same await with
// no timer, normalized into the timed shape so one match handles both.
let outcome = match wait {
Some(dur) => tokio::time::timeout(dur, result_rx).await,
None => Ok(result_rx.await),
};
let result = match outcome {
Ok(Ok(r)) => r,
Ok(Err(_recv_error)) => {
return Err(xai_tool_runtime::ToolError::execution(
xai_tool_protocol::ToolId::new("ask_user_question").expect("valid"),
"User question session ended unexpectedly (client may have disconnected)",
));
}
Err(_elapsed) => {
tracing::info!(
question_count,
timeout_secs = ?wait.map(|d| d.as_secs()),
"User question timed out; continuing without answers"
);
// Drop the oneshot receiver on return. The shell coordinator
// races `result_tx.closed()` against ACP so it unblocks and
// can open the next questionnaire (stale UI is cancelled when
// a new ext_method arrives). Same model text as cancel.
return Ok(AskUserQuestionOutput::UserAnswered {
message: unanswered.to_string(),
});
}
};View on GitHub (pinned to bc7f02eddd)
Solutions
- Verify the client (ACP peer) is still connected and alive before invoking ask_user_question; reconnect the session and re-run the agent step.
- Check shell logs around the failure for coordinator/client disconnect or panic messages to identify why result_tx was dropped.
- Retry the tool call after restoring the session; the error is transient if the disconnect was temporary.
- If running non-interactively, configure non_interactive/wait budget params so the tool degrades to an unanswered result instead of blocking on a channel.
Example fix
// before: calling the tool from a script with no live client
await session.prompt("ask_user_question", { questions });
// after: guard on client connectivity / use non-interactive mode
if (!session.clientConnected()) {
params.set("ask_user_question", { non_interactive: true });
}
await session.prompt("ask_user_question", { questions }); Defensive patterns
Strategy: try-catch
Validate before calling
// before calling, ensure an interactive client is attached
if (!session.clientConnected || !session.clientConnected()) {
params.set("ask_user_question", { non_interactive: true });
} Type guard
fn has_live_client(res: &Resources) -> bool {
res.get::<NotificationHandle>().is_some()
} Try / catch
try {
const out = await tool("ask_user_question", { questions });
} catch (e) {
if (String(e.message).includes("session ended unexpectedly")) {
await reconnect(); // or fall back to non-interactive defaults
} else { throw e; }
} Prevention
- Only call ask_user_question when a live interactive client is attached
- Use non_interactive mode for headless/CI runs
- Monitor client disconnect events and cancel pending questionnaires promptly
- Catch this error and fall back to sensible defaults instead of failing the whole run
When it happens
Trigger: The coordinator/client holding `result_tx` is dropped before replying — e.g. the ACP client disconnects mid-questionnaire, the shell coordinator task is cancelled/panics, or the user closes the session while questions are pending. Distinguishable from a timeout: the wait budget did not elapse; the channel closed early.
Common situations: User closes the editor/CLI window while a question is pending; IDE extension host restarts during an agent run; the client process crashes or is killed; network drop tears down the ACP session; running the tool headlessly where no interactive client exists.
Related errors
- User question session ended unexpectedly (coordinator channe
- PTY write channel closed
- terminal writer stopped
- OidcError::CallbackChannelClosed
- resources persistence writer stopped
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/5591fe968417ec05.
Report an issue: GitHub.