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
- Check that the skill file still exists at the path printed in the error (list the directory).
- Restore read permission (chmod u+r) or ownership of the file.
- Trigger a skills re-scan (reopen the panel or restart Zed) so the stale entry disappears.
- 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
- Watch the skills directory and re-scan on change instead of caching paths.
- Filter skill candidates by existence before showing them in the picker.
- Distinguish NotFound (drop the entry) from PermissionDenied (warn) when handling read failures.
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
- Unexpected response structure: ${JSON.stringify(data)}
- cannot capture writable sandbox path `{}`
- cannot re-verify approved sandbox write grant `{}` (if the d
- project path not found for symbol mention {abs_path:?}
- Thread mentions are only supported for the native agent
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/e8add794ee7fb651.
Report an issue: GitHub.