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 exclusionView on GitHub (pinned to 88bb9c8533)
Solutions
- Verify that owned/exec_cache is only populated inside the branch guarded by sop_reassembly (see turn/mod.rs around 1953-2134).
- Upgrade to a consistent zeroclaw version; mixed crate versions can break this pairing.
- 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
- Keep SOP reassembly config and delegating steps consistent in the SOP definition.
- Use one consistent zeroclaw version across crates; do not mix builds of runtime and config loaders.
- Wrap SOP execution in catch_unwind at the daemon boundary and log the backtrace for upstream reports.
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
- needs_reassembly implies a step agent alias
- Schema missing required 'type' field
- purge_agent not supported by this memory backend
- rename_agent not supported by this memory backend
- memory backend '{}' does not support StoreOptions kind/pinne
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/573a30db482503b6.
Report an issue: GitHub.