xai-org/grok-build · warning

cancelled after git worktree add

Error message

cancelled after git worktree add

What it means

execute_copy_worktree installs a PartialWorktreeGuard and then checks the cancellation token immediately after `git worktree add` but before the expensive parallel file copy. If cancellation was requested during the git phase, it bails with this message; the drop guard then reclaims the partial destination tree so no half-built worktree is left behind.

Source

Thrown at crates/codegen/xai-fast-worktree/src/worktree/execute.rs:953

    let dest_str = dest.to_string_lossy().to_string();

    // Get modified files from source (for dirty state preservation or clean modes).
    // This runs in parallel with worktree creation conceptually, but since we're sync now,
    // we run it after worktree add for simplicity (the worktree add is typically fast).
    git::worktree_add_no_checkout(&source, &dest_str, &git_ref)?;
    tracing::debug!(elapsed = ?start.elapsed(), "git worktree add --no-checkout complete");

    // `git worktree add` created dest + its `.git/worktrees/<name>` registration.
    // From here, any early return (cancel or a hard error in copy/finalize/
    // bad-ref) must reclaim both so a later pinned-dest fast path can't adopt a
    // partial tree. No background threads touch dest in this path, so a drop
    // guard is sufficient.
    let guard = PartialWorktreeGuard::new(&dest);

    // Check cancellation after git worktree add (before the expensive copy).
    if cancellation_token.is_cancelled() {
        anyhow::bail!("cancelled after git worktree add");
    }

    // Get modified files
    let modified_result = git::get_modified_files(&source_root)?;
    let modified_files_in_source = Arc::new(modified_result.paths);
    let dirty_files_report = Some(modified_result.report);

    // For CleanTracked/CleanAll: we need to skip modified files during copy
    let modified_files_for_skip = match &working_tree {
        WorkingTreeMode::PreserveWorkingTree => None,
        WorkingTreeMode::CleanTracked | WorkingTreeMode::CleanAll => {
            Some(Arc::clone(&modified_files_in_source))
        }
    };

    // Phase 2: Parallel CoW copy of unignored files.
    // IMPORTANT: Copy from source_root (git root), not source (which might be a subdirectory).
    let copy_start = std::time::Instant::now();

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. This is cooperative cancellation working as designed — re-issue the create request if the worktree is still needed (destination was reclaimed).
  2. Avoid cancelling during create; wait for completion or reserve a longer deadline.
  3. If cancellation was accidental, ensure the token is not shared/triggered by an unrelated shutdown path.
  4. Check the destination path is gone (guard reclaimed it) before retrying to avoid 'already exists' errors.
Defensive patterns

Strategy: try-catch

Try / catch

match create_worktree(&plan).await {
    Err(e) if e.to_string().contains("cancelled after git worktree add") => {
        tracing::info!("creation cancelled; dest reclaimed, safe to retry");
        // retry only if cancellation was not user-intentional
    }
    other => other,
}

Prevention

When it happens

Trigger: A shutdown/timeout/abort triggered the CancellationToken while `git worktree add` was still running (or between its completion and the copy start); the caller dropped or cancelled the future driving execute_create_worktree_dispatch's copy path.

Common situations: User hits Ctrl-C or a supervisor times out a long create; bulk job orchestrator cancels pending worktree creations; request deadline expires just as creation starts.

Related errors


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