xai-org/grok-build · error

daemon RemoveWorktree failed: {e}

Error message

daemon RemoveWorktree failed: {e}

What it means

remove_nfs_worktree first asks the grove daemon to remove the worktree via client.remove_worktree. If the daemon accepts the ping but the RemoveWorktree RPC returns an error, this wraps and surfaces it as 'daemon RemoveWorktree failed', aborting the local remove path.

Source

Thrown at crates/codegen/xai-fast-worktree/src/nfs/remove.rs:42

        if lookup_from_markers(worktree_path).is_none() {
            bail!(
                "{} is a live grove mount without a backing marker; refusing rm -rf",
                worktree_path.display()
            );
        }
    } else if dest_is_mountpoint(worktree_path) || lookup_nfs_meta(worktree_path).is_none() {
        return Ok(None);
    }
    remove_nfs_worktree(worktree_path)
}
fn remove_nfs_worktree(worktree_path: &Path) -> Result<Option<RemoveReport>> {
    let opts = nfs_opts_from_env_and_meta(None);
    let client = NfsWorktreeClient::from_opts(&opts);
    if client.ping() {
        match client.remove_worktree(worktree_path, false) {
            Ok(()) => return report_after_daemon_unmount(worktree_path),
            Err(e) => {
                bail!("daemon RemoveWorktree failed: {e}");
            }
        }
    }
    if dest_is_mountpoint(worktree_path) {
        if lookup_from_markers(worktree_path).is_none() {
            bail!(
                "{} is still a mountpoint without a grove marker; refusing umount/rm",
                worktree_path.display()
            );
        }
        plain_umount(worktree_path)?;
    }
    if !super::dest_is_known_unmounted(worktree_path) {
        bail!(
            "unmount of {} could not be verified (still mounted or mount table \
             inconclusive); retaining backing and pin",
            worktree_path.display()
        );

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Inspect the inner error (source chain) — usually EBUSY/permission — and close processes using the mount, then retry
  2. Check daemon logs for the RemoveWorktree failure reason
  3. Restart the daemon to clear stale state, then retry try_nfs_remove
  4. Fall back to the manual path: umount the dest, verify unmounted, then remove backing yourself

Example fix

// before
try_nfs_remove(&path)?;
// after
if let Err(e) = try_nfs_remove(&path) {
    eprintln!("daemon remove failed: {e:#}");
    Command::new("umount").arg(&path).status()?;
    // verify unmounted, then remove backing dir manually
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure no processes hold the mount before daemon removal
let busy = Command::new("fuser").arg("-m").arg(&path)
    .stdout(Stdio::null()).status().map(|s| s.success());
if busy == Ok(true) { eprintln!("mount is busy; close processes first"); }

Try / catch

match client.remove_worktree(worktree_path, false) {
    Ok(()) => {}
    Err(e) => {
        eprintln!("RemoveWorktree failed: {e:#}"); // inspect source chain for EBUSY/EACCES
        // fall back to manual umount + verified removal
    }
}

Prevention

When it happens

Trigger: Calling try_nfs_remove while the daemon is up but its remove_worktree fails: dest busy/EBUSY, backing dir missing, permission denied, worktree id lookup failed, or daemon-side unmount rejected.

Common situations: A process still holds files open under the mount (EBUSY); daemon lost track of the worktree after a config change; running the remove as a different user than the daemon.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/1b2e8065e9e9c1b9. Report an issue: GitHub.