{"record":{"id":"573a30db482503b6","repo":"zeroclaw-labs/zeroclaw","slug":"owned-implies-a-reassembly-handle","errorCode":null,"errorMessage":"owned implies a reassembly handle","messagePattern":"owned implies a reassembly handle","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/agent/turn/mod.rs","lineNumber":2072,"sourceCode":"                            eff_temperature,\n                            eff_max_tool_iterations,\n                            eff_strict_tool_parsing,\n                            eff_parallel_tools,\n                            eff_max_tool_result_chars,\n                            eff_context_token_budget,\n                            eff_dedup_exempt_tools,\n                            eff_pacing,\n                        ) = match owned {\n                            Some(o) => (\n                                o.temperature,\n                                o.agent.resolved.max_tool_iterations,\n                                o.agent.resolved.strict_tool_parsing,\n                                o.agent.resolved.parallel_tools,\n                                o.agent.resolved.max_tool_result_chars,\n                                o.agent.resolved.effective_context_budget(),\n                                o.agent.resolved.tool_call_dedup_exempt.as_slice(),\n                                &sop_reassembly\n                                    .expect(\"owned implies a reassembly handle\")\n                                    .config\n                                    .pacing,\n                            ),\n                            None => (\n                                temperature,\n                                max_tool_iterations,\n                                strict_tool_parsing,\n                                parallel_tools,\n                                max_tool_result_chars,\n                                context_token_budget,\n                                dedup_exempt_tools,\n                                pacing,\n                            ),\n                        };\n\n                        // Exclusions for a cross-agent step derive from the\n                        // STEP agent: its own `tool_filter_groups` gate over\n                        // the step context. The parent's turn-level exclusion","sourceCodeStart":2054,"sourceCodeEnd":2090,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/agent/turn/mod.rs#L2054-L2090","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate the SOP reassembly config exists whenever any step delegates:\nlet delegates = sop.steps.iter().any(|s| s.agent.is_some());\nanyhow::ensure!(!delegates || sop.reassembly.is_some(),\n    \"SOP '{}' has delegating steps but no reassembly configuration\", sop.name);","typeGuard":null,"tryCatchPattern":"let result = std::panic::catch_unwind(std::assert_unwind_safe(|| turn.execute(sop)));","preventionTips":["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."],"tags":["rust","sop","agent-turn","invariant","panic","internal"],"backgroundTag":"internal-invariant-violation","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}