Hmbown/CodeWhale · error
registered shell tool context
Error message
registered shell tool context
What it means
Panic while applying a user's approval to a sandbox escalation. `batch_tool_context` comes from `self.live_tool_context(tool_registry)` (engine.rs:5467), which returns `None` only when no tool registry exists (`registry?` at the top of the function). When the approval decision is `Approved` and the model requested a policy, the code clones that context to call `with_elevated_sandbox_policy`. The expect assumes that a bash escalation path implies a registry-backed live context; it fires when escalation approval is reached with the registry absent.
Source
Thrown at crates/tui/src/core/engine/turn_loop.rs:3177
Ok(ApprovalResult::Approved) => {
let decision = if model_requested_policy.is_some() {
"approved_with_requested_policy"
} else {
"approved"
};
emit_tool_audit(json!({
"event": "tool.approval_decision",
"tool_id": tool_id.clone(),
"tool_name": tool_name.clone(),
"decision": decision,
"policy": model_requested_policy.as_ref().map(|policy| format!("{policy:?}")),
"caller": caller_type_for_tool_use(tool_caller.as_ref()),
}));
if let Some(policy) = model_requested_policy {
let elevated_context = Some(
batch_tool_context
.clone()
.expect("registered shell tool context")
.with_elevated_sandbox_policy(policy),
);
(
None,
elevated_context,
Some(ToolApprovalStamp::ApprovedWithPolicy),
)
} else {
(None, None, Some(ToolApprovalStamp::ApprovedByUser))
}
}
Ok(ApprovalResult::Denied) => {
emit_tool_audit(json!({
"event": "tool.approval_decision",
"tool_id": tool_id.clone(),
"tool_name": tool_name.clone(),
"decision": "denied",
"caller": caller_type_for_tool_use(tool_caller.as_ref()),View on GitHub (pinned to 0c42157ee5)
Solutions
- Replace the expect with `batch_tool_context.as_ref().map(|ctx| ctx.clone().with_elevated_sandbox_policy(policy))` and treat `None` as fail-closed: emit a denial result stating the elevated context is unavailable.
- Assert the registry invariant at batch entry and route escalation-capable calls away when it is missing.
- Document that `live_tool_context` may return `None` only for registry absence, and keep that contract.
- Add a test that runs the batch path with no registry and a `sandbox_permissions`-bearing call.
Example fix
// before
let elevated_context = Some(
batch_tool_context.clone().expect("registered shell tool context")
.with_elevated_sandbox_policy(policy),
);
// after: fail closed when no live context exists
let elevated_context = batch_tool_context
.as_ref()
.map(|ctx| ctx.clone().with_elevated_sandbox_policy(policy)); Defensive patterns
Strategy: type-guard
Validate before calling
if tool_input.get("sandbox_permissions").is_some() && batch_tool_context.is_none() {
// fail closed before the approval prompt is ever shown
return tool_error("sandbox escalation requires a live tool context");
} Type guard
fn can_apply_escalation(ctx: &Option<ToolContext>, requested: bool) -> bool {
!requested || ctx.is_some()
} Prevention
- Assert the tool registry is present at batch entry when any call may request escalation.
- When embedding the engine, always construct and pass the ToolRegistry instead of None.
- Treat escalation approval code as requiring a live context by contract; fail closed, never expect.
When it happens
Trigger: A batch execution path running with `tool_registry = None` while a tool call carries `sandbox_permissions` and the user approves it: the registry is lost or never passed on a new execution entry point, or `live_tool_context` is refactored to return `None` in more cases while escalation handling still assumes `Some`.
Common situations: Embedding the engine in tests or fleet workers without a full tool registry; refactors that make the registry optional; split-brain between escalation planning (which does not need the registry) and approval application (which does).
Related errors
- validated sandbox permission
- sandbox escalation was validated while planning
- cancelled tool result is always model-visible
- runtime event JSON is serializable
- validated Fleet tool authority envelope must serialize
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/a077782ca5a7ad43.
Report an issue: GitHub.