zed-industries/zed · error

Failed to read skill file {}: {}

Error message

Failed to read skill file {}: {}

What it means

Confirming a skill @-mention first tries agent_skills::builtin_skill_content for built-in skills (synthetic paths, compiled into the binary); everything else is read from disk with std::fs::read_to_string. This error wraps that IO failure: the skill file was listed but could not be read at confirmation time.

Source

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

        })
    }

    fn confirm_mention_for_skill(
        &self,
        skill_file_path: PathBuf,
        cx: &mut Context<Self>,
    ) -> Task<Result<Mention>> {
        // Built-in skills have synthetic paths that don't exist on disk;
        // serve their content directly from the compiled-in data.
        if let Some(content) = agent_skills::builtin_skill_content(&skill_file_path) {
            return Task::ready(Ok(Mention::Text {
                content: content.to_string(),
                tracked_buffers: Vec::new(),
            }));
        }
        cx.background_spawn(async move {
            let content = std::fs::read_to_string(&skill_file_path).map_err(|e| {
                anyhow!(
                    "Failed to read skill file {}: {}",
                    skill_file_path.display(),
                    e
                )
            })?;
            Ok(Mention::Text {
                content,
                tracked_buffers: Vec::new(),
            })
        })
    }

    pub fn confirm_mention_for_selection(
        &mut self,
        source_range: Range<text::Anchor>,
        selections: Vec<(Entity<Buffer>, Range<text::Anchor>, Range<usize>)>,
        editor: Entity<Editor>,
        workspace: WeakEntity<Workspace>,

View on GitHub (pinned to bc538def45)

Solutions

  1. Check that the skill file still exists at the path printed in the error (list the directory).
  2. Restore read permission (chmod u+r) or ownership of the file.
  3. Trigger a skills re-scan (reopen the panel or restart Zed) so the stale entry disappears.
  4. If the skill is built-in, use its canonical name so the compiled-in content path is taken instead of the filesystem.
Defensive patterns

Strategy: validation

Validate before calling

// before confirming a skill mention, probe the file on a background thread
let exists = smol::unblock({
    let path = skill_file_path.clone();
    move || std::fs::metadata(&path).map(|m| m.is_file()).unwrap_or(false)
})
.await;
if !exists {
    // drop the candidate from the picker instead of confirming
}

Try / catch

match std::fs::read_to_string(&skill_file_path) {
    Ok(content) => content,
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
        remove_skill_from_list(&skill_file_path); // stale entry
        continue;
    }
    Err(e) => return Err(e.into()), // PermissionDenied etc: surface to user
}

Prevention

When it happens

Trigger: Mentioning a user or project skill whose file was deleted, renamed, or moved after the skill list was populated; an unreadable file (permissions or ownership); a path on an unmounted removable drive or network share; a stale skill index after relocating the project directory.

Common situations: Editing ~/.config/zed/skills or .zed/skills while the skill picker is open; dotfile sync tools replacing skill files; running as a different user; skill directories on external media; a custom skill whose name collides with a built-in but only exists on disk.

Related errors


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