Hmbown/CodeWhale · critical

failed to durably register write-capable sub-agent before la

Error message

failed to durably register write-capable sub-agent before launch: {error}

What it means

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.

Source

Thrown at crates/tui/src/tools/subagent/mod.rs:6527

        // while the manager write lock still excludes the child; then launch.
        // A crash can therefore leave an interrupted owner, never an accepted
        // edit with no durable scope/identity record.
        if write_capable {
            self.agents.insert(agent_id.clone(), agent);
            let persist_result = self.persist_state_synchronously();
            agent = self
                .agents
                .remove(&agent_id)
                .expect("pre-launch agent remains registered under manager lock");
            if let Err(error) = persist_result {
                let (worker_records, coordination) = durable_launch_snapshot
                    .expect("write-capable launch captured a registration snapshot");
                self.worker_records = worker_records;
                self.coordination = coordination;
                if let Some(lifecycle) = agent.work_lifecycle.as_ref() {
                    let _ = lifecycle.reconcile_state(OwnerState::Failed, 1, None);
                }
                return Err(anyhow!(
                    "failed to durably register write-capable sub-agent before launch: {error}"
                ));
            }
        }

        if let Some(mb) = runtime.mailbox.as_ref() {
            let _ = mb.send(MailboxMessage::started(&agent_id, agent_type.clone()));
        }

        if let Some(event_tx) = runtime.event_tx.clone() {
            let _ = event_tx.try_send(Event::AgentSpawned {
                owner_session_id: runtime.context.state_namespace.clone(),
                id: agent_id.clone(),
                prompt: prompt.clone(),
                parent_run_id: runtime.parent_agent_id.clone(),
                spawn_depth: runtime.spawn_depth,
                // The model the child was actually installed with. Read here
                // rather than from session state so a later `/model` switch

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Resolve the state-store IO failure (space, permissions, mount) revealed by the embedded {error}
  2. Validate the state path is writable and the state file parses before retrying
  3. Retry the launch once the store is healthy; the rollback means no partial agent is left behind, so a clean retry is safe
  4. If writes cannot be made durable in this environment, switch the workload to read-only or isolated-worktree children

Example fix

// before
let agent = manager.spawn_subagent_from_input(&write_request).await?;

// after
let agent = match manager.spawn_subagent_from_input(&write_request).await {
    Err(e) if e.to_string().starts_with("failed to durably register") => {
        repair_state_store(&state_path).await?; // fix IO root cause first
        manager.spawn_subagent_from_input(&write_request).await?
    }
    other => other?,
};
Defensive patterns

Strategy: try-catch

Validate before calling

// Same pre-flight as the contention case: verify the durable seam first.
anyhow::ensure!(
    std::fs::metadata(&state_path).map(|m| !m.permissions().readonly()).unwrap_or(false),
    "state path not writable; write-capable launch would abort"
);

Try / catch

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.

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/02f5c8fe278dae7a. Report an issue: GitHub.