zeroclaw-labs/zeroclaw · error

owned implies a reassembly handle

Error message

owned implies a reassembly handle

What it means

When a step has an owned (re-assembled) execution surface, the turn engine reads pacing configuration from the SOP reassembly handle, asserting "owned implies a reassembly handle". The code above guarantees owned is Some only when reassembly occurred, which requires sop_reassembly to be present, so this expect is an internal consistency check that should never fire.

Source

Thrown at crates/zeroclaw-runtime/src/agent/turn/mod.rs:2072

                            eff_temperature,
                            eff_max_tool_iterations,
                            eff_strict_tool_parsing,
                            eff_parallel_tools,
                            eff_max_tool_result_chars,
                            eff_context_token_budget,
                            eff_dedup_exempt_tools,
                            eff_pacing,
                        ) = match owned {
                            Some(o) => (
                                o.temperature,
                                o.agent.resolved.max_tool_iterations,
                                o.agent.resolved.strict_tool_parsing,
                                o.agent.resolved.parallel_tools,
                                o.agent.resolved.max_tool_result_chars,
                                o.agent.resolved.effective_context_budget(),
                                o.agent.resolved.tool_call_dedup_exempt.as_slice(),
                                &sop_reassembly
                                    .expect("owned implies a reassembly handle")
                                    .config
                                    .pacing,
                            ),
                            None => (
                                temperature,
                                max_tool_iterations,
                                strict_tool_parsing,
                                parallel_tools,
                                max_tool_result_chars,
                                context_token_budget,
                                dedup_exempt_tools,
                                pacing,
                            ),
                        };

                        // Exclusions for a cross-agent step derive from the
                        // STEP agent: its own `tool_filter_groups` gate over
                        // the step context. The parent's turn-level exclusion

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Verify that owned/exec_cache is only populated inside the branch guarded by sop_reassembly (see turn/mod.rs around 1953-2134).
  2. Upgrade to a consistent zeroclaw version; mixed crate versions can break this pairing.
  3. Report upstream with the SOP definition and backtrace if it reproduces unmodified.
Defensive patterns

Strategy: validation

Validate before calling

// Validate the SOP reassembly config exists whenever any step delegates:
let delegates = sop.steps.iter().any(|s| s.agent.is_some());
anyhow::ensure!(!delegates || sop.reassembly.is_some(),
    "SOP '{}' has delegating steps but no reassembly configuration", sop.name);

Try / catch

let result = std::panic::catch_unwind(std::assert_unwind_safe(|| turn.execute(sop)));

Prevention

When it happens

Trigger: Running an SOP step that delegates to another agent with an owned execution surface while sop_reassembly is None. Only reachable if the code path that populates owned diverges from the path that checks sop_reassembly (e.g. a partial refactor).

Common situations: Patched runtimes where owned is populated from a different source than sop_reassembly; version mismatches between the SOP reassembly config loader and the turn loop.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/573a30db482503b6. Report an issue: GitHub.