tinyhumansai/openhuman · error

embedder tool-hook arguments poisoned

Error message

embedder tool-hook arguments poisoned

What it means

Mutex poisoning on the shared tool-arguments cache in the tinyagents middleware: a panic in a hook (before_tool/after_tool) or another thread while holding the arguments mutex poisons it, and the next lock() in the embedder tool-hook path expects success. The denial/error text shown is a symptom; the original panic earlier in the log is the cause.

Source

Thrown at src/openhuman/agent/tinyagents/middleware.rs:1538

            arguments: call.arguments.clone(),
            success: None,
            duration_ms: None,
        };
        for hook in &self.hooks {
            hook.before_tool(&context).await.map_err(|error| {
                tinyagents::error::TinyAgentsError::Tool(format!(
                    "tool hook '{}' denied {}: {error:#}",
                    hook.name(),
                    context.tool_name
                ))
            })?;
        }
        // Cache the (already-recovered) arguments only once every hook approved
        // the call: a vetoed call never reaches `after_tool`, so storing it here
        // would leak a cache entry for the turn.
        self.arguments_by_call_id
            .lock()
            .expect("embedder tool-hook arguments poisoned")
            .insert(call.id.clone(), call.arguments.clone());
        Ok(())
    }

    async fn after_tool(
        &self,
        _ctx: &mut RunContext<()>,
        _state: &(),
        result: &mut TaToolResult,
    ) -> TaResult<()> {
        let arguments = self
            .arguments_by_call_id
            .lock()
            .expect("embedder tool-hook arguments poisoned")
            .remove(&result.call_id)
            .unwrap_or(serde_json::Value::Null);
        let context = crate::openhuman::agent::hooks::ToolHookContext {
            event: crate::openhuman::agent::hooks::ToolHookEvent::PostToolUse,

View on GitHub (pinned to 7491200858)

Solutions

  1. Locate the poisoning panic in the logs (a hook that unwound mid-lock) and fix it
  2. Use lock().unwrap_or_else(|e| e.into_inner()) to salvage cached arguments when poison is tolerable
  3. Isolate each hook's body so one panicking hook cannot unwind through the mutex guard
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at src/openhuman/agent/tinyagents/middleware.rs:1538 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/b61f2fe13f82a398. Report an issue: GitHub.