{"record":{"id":"02f5c8fe278dae7a","repo":"Hmbown/CodeWhale","slug":"failed-to-durably-register-write-capable-sub-agent","errorCode":null,"errorMessage":"failed to durably register write-capable sub-agent before launch: {error}","messagePattern":"failed to durably register write-capable sub-agent before launch: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":6527,"sourceCode":"        // while the manager write lock still excludes the child; then launch.\n        // A crash can therefore leave an interrupted owner, never an accepted\n        // edit with no durable scope/identity record.\n        if write_capable {\n            self.agents.insert(agent_id.clone(), agent);\n            let persist_result = self.persist_state_synchronously();\n            agent = self\n                .agents\n                .remove(&agent_id)\n                .expect(\"pre-launch agent remains registered under manager lock\");\n            if let Err(error) = persist_result {\n                let (worker_records, coordination) = durable_launch_snapshot\n                    .expect(\"write-capable launch captured a registration snapshot\");\n                self.worker_records = worker_records;\n                self.coordination = coordination;\n                if let Some(lifecycle) = agent.work_lifecycle.as_ref() {\n                    let _ = lifecycle.reconcile_state(OwnerState::Failed, 1, None);\n                }\n                return Err(anyhow!(\n                    \"failed to durably register write-capable sub-agent before launch: {error}\"\n                ));\n            }\n        }\n\n        if let Some(mb) = runtime.mailbox.as_ref() {\n            let _ = mb.send(MailboxMessage::started(&agent_id, agent_type.clone()));\n        }\n\n        if let Some(event_tx) = runtime.event_tx.clone() {\n            let _ = event_tx.try_send(Event::AgentSpawned {\n                owner_session_id: runtime.context.state_namespace.clone(),\n                id: agent_id.clone(),\n                prompt: prompt.clone(),\n                parent_run_id: runtime.parent_agent_id.clone(),\n                spawn_depth: runtime.spawn_depth,\n                // The model the child was actually installed with. Read here\n                // rather than from session state so a later `/model` switch","sourceCodeStart":6509,"sourceCodeEnd":6545,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tools/subagent/mod.rs#L6509-L6545","documentation":"A write-capable sub-agent must be durably registered before it starts; if that pre-launch persistence fails, the manager rolls everything back — the agent is removed from the registry, the captured worker-record/coordination snapshot is restored, the work lifecycle is reconciled to Failed — and the launch aborts with the underlying persistence error. This refuses to run a writer that crash-recovery cannot see, which is the safe direction to fail.","triggerScenarios":"The pre-launch persist_state_synchronously (or claim registration) failing on IO errors — disk full, permissions, read-only filesystem; a damaged state file rejecting the registration write; state path on a filesystem with broken atomic rename semantics.","commonSituations":"Same class as the contention-receipt failure: disk exhaustion mid-session, containerized deployments with volume permission drift, or a corrupted coordination state file encountered exactly at write-capable spawn time.","solutions":["Resolve the state-store IO failure (space, permissions, mount) revealed by the embedded {error}","Validate the state path is writable and the state file parses before retrying","Retry the launch once the store is healthy; the rollback means no partial agent is left behind, so a clean retry is safe","If writes cannot be made durable in this environment, switch the workload to read-only or isolated-worktree children"],"exampleFix":"// before\nlet agent = manager.spawn_subagent_from_input(&write_request).await?;\n\n// after\nlet agent = match manager.spawn_subagent_from_input(&write_request).await {\n    Err(e) if e.to_string().starts_with(\"failed to durably register\") => {\n        repair_state_store(&state_path).await?; // fix IO root cause first\n        manager.spawn_subagent_from_input(&write_request).await?\n    }\n    other => other?,\n};","handlingStrategy":"try-catch","validationCode":"// Same pre-flight as the contention case: verify the durable seam first.\nanyhow::ensure!(\n    std::fs::metadata(&state_path).map(|m| !m.permissions().readonly()).unwrap_or(false),\n    \"state path not writable; write-capable launch would abort\"\n);","typeGuard":null,"tryCatchPattern":"Match the 'failed to durably register write-capable sub-agent' prefix, surface the embedded {error}, run the state-store repair steps, then retry the spawn exactly once — the built-in rollback guarantees no partial agent survives, so a single clean retry is safe.","preventionTips":["Alert on any durable-registration failure: it means crash recovery cannot see writers","Test the write-capable spawn path in CI with a real temp state directory so config regressions surface early","Prefer read-only or isolated-worktree children in environments where durable state cannot be guaranteed"],"tags":["subagent","rust","persistence","io-error","rollback","write-permissions","launch-aborted"],"backgroundTag":"state-persistence-failure","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}