zed-industries/zed · warning

worktree not found

Error message

worktree not found

What it means

The directory-mention flow resolved a ProjectPath (which embeds worktree_id) and immediately calls project.worktree_for_id; None means the worktree was removed from the project in between. Because the id came from a worktree that existed a moment earlier, this is a teardown/removal race rather than a bad path.

Source

Thrown at crates/agent_ui/src/mention_set.rs:1260

        files
    }

    let Some(project_path) = project
        .read(cx)
        .project_path_for_absolute_path(&abs_path, cx)
    else {
        return Task::ready(Err(anyhow!(
            "project path not found for directory mention {abs_path:?}"
        )));
    };
    let Some(entry) = project.read(cx).entry_for_path(&project_path, cx) else {
        return Task::ready(Err(anyhow!("project entry not found")));
    };
    let directory_path = entry.path.clone();
    let worktree_id = project_path.worktree_id;
    let Some(worktree) = project.read(cx).worktree_for_id(worktree_id, cx) else {
        return Task::ready(Err(anyhow!("worktree not found")));
    };
    let project = project.clone();
    cx.spawn(async move |cx| {
        let file_paths = worktree.read_with(cx, |worktree, _cx| {
            collect_files_in_path(worktree, &directory_path)
        });
        let descendants_future = cx.update(|cx| {
            futures::future::join_all(file_paths.into_iter().map(
                |(worktree_path, full_path): (Arc<RelPath>, String)| {
                    let rel_path = worktree_path
                        .strip_prefix(&directory_path)
                        .map_or_else(|_| worktree_path.clone(), |rel_path| rel_path.into());

                    let open_task = project.update(cx, |project, cx| {
                        project.buffer_store().update(cx, |buffer_store, cx| {
                            let project_path = ProjectPath {
                                worktree_id,
                                path: worktree_path,

View on GitHub (pinned to bc538def45)

Solutions

  1. Retry the mention after the project settles; the path re-resolves against the remaining worktrees.
  2. Treat as cancellation if the window is closing.
  3. In code, re-validate that the worktree still exists right before use and surface a 'directory no longer available' message.
Defensive patterns

Strategy: validation

Validate before calling

// re-resolve the worktree immediately before spawning the async work
let Some(worktree) = project.read(cx).worktree_for_id(project_path.worktree_id, cx) else {
    return Task::ready(Err(anyhow!("directory no longer available")));
};

Try / catch

match confirm_task.await {
    Ok(mention) => { /* attach */ }
    Err(err) if err.to_string() == "worktree not found" => {
        show_user("That worktree was removed from the project")
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Removing or closing a worktree from the project while a directory mention confirmation is running; project teardown racing the spawned mention task.

Common situations: Closing a multi-root project's root just as a mention is confirmed; rapid workspace restructuring; tests exercising removal races.

Related errors


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/04f24dc6f61d5f5b. Report an issue: GitHub.