tinyhumansai/openhuman · error
CapturingObserver steps mutex poisoned
Error message
CapturingObserver steps mutex poisoned
What it means
Mutex poisoning on CapturingObserver's steps mutex in the flows dry-run tooling: the observer collects ExecutionStep records (including null-resolution diagnostics) during the sandbox run; if a panic unwound while that mutex was held, later lock() calls in DryRunWorkflowTool's inspection path hit PoisonError and this expect fires. The dry-run result is lost; the originating panic is the real fault.
Source
Thrown at src/openhuman/flows/builder_tools.rs:3463
/// node's [`ExecutionStep`](tinyflows::observability::ExecutionStep) — in
/// particular its `diagnostics` (null-resolved `=`-expressions the engine
/// traced during that node's config resolution) — so [`DryRunWorkflowTool`]
/// can inspect them once the sandbox run settles. See the struct's "Null-
/// resolution check" doc for why this exists.
/// `pub(crate)` (not private) so [`crate::openhuman::flows::ops::validate_required_arg_resolvability`]
/// (issue B18 — escalating a null-resolved REQUIRED outbound arg to a hard
/// authoring-time reject) can run the identical sandbox-capture shape without
/// duplicating this struct.
#[derive(Default)]
pub(crate) struct CapturingObserver {
steps: std::sync::Mutex<Vec<tinyflows::observability::ExecutionStep>>,
}
impl tinyflows::observability::RunObserver for CapturingObserver {
fn on_step_finish(&self, step: &tinyflows::observability::ExecutionStep) {
self.steps
.lock()
.expect("CapturingObserver steps mutex poisoned")
.push(step.clone());
}
}
impl CapturingObserver {
/// A snapshot of every step recorded so far (steps are pushed
/// synchronously from `on_step_finish`, so once the run's future resolves
/// every step it will ever record is already present).
pub(crate) fn steps(&self) -> Vec<tinyflows::observability::ExecutionStep> {
self.steps
.lock()
.expect("CapturingObserver steps mutex poisoned")
.clone()
}
}
// ─────────────────────────────────────────────────────────────────────────────
// save_workflow — persist a built graph onto an EXISTING saved flowView on GitHub (pinned to 7491200858)
Solutions
- Fix the panic that occurred mid-capture (visible earlier in the run log)
- Scope the steps lock to the shortest possible region so engine panics cannot hold it
- Recover with into_inner() if partial captured steps are still useful for diagnostics
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at src/openhuman/flows/builder_tools.rs:3463 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/21280cdb7a666845.
Report an issue: GitHub.