Hmbown/CodeWhale · error · ToolError
Skill ` ` is registered at but that file no longer exists…
Error message
Skill `{}` is registered at {} but that file no longer exists on disk, so the skill did not load. Restore the file, or fix the skills directory it came from (`skills_dir` in config.toml, `$CODEWHALE_HOME`, or the OS home) — the path above shows exactly where the runtime looked. What it means
ensure_native_skill_file_present checks that a registered skill's backing file still exists on disk before use. If the skill registry entry points to a file that has vanished, it logs a warning and returns ToolError::execution_failed with this message, so the failure is loud rather than a silent no-op.
Solutions
- Restore the skill file at the exact path shown in the message (skill.path)
- Fix `skills_dir` in config.toml (or set $CODEWHALE_HOME / ensure the OS home) so it points at the directory that actually contains the skill files, then restart
- Re-install or re-download the missing skill into the configured skills directory
Example fix
# before skills_dir = "/home/user/old-dotfiles/skills" # after skills_dir = "/home/user/dotfiles/skills"
Defensive patterns
Strategy: validation
Validate before calling
// before invoking a skill
let skills_dir = std::env::var("CODEWHALE_HOME").map(|h| std::path::PathBuf::from(h).join("skills")).unwrap_or_else(|_| dirs::home_dir().unwrap().join(".codewhale/skills"));
assert!(skills_dir.is_dir(), "skills_dir missing: {}", skills_dir.display());
for f in std::fs::read_dir(&skills_dir).unwrap() {
println!("skill file: {}", f.unwrap().path().display());
} Try / catch
match tool.execute(skill_invocation) {
Err(ToolError::ExecutionFailed(msg)) if msg.contains("no longer exists on disk") => {
// restore the file at the path embedded in msg or fix skills_dir, then retry
eprintln!("skill file missing: {msg}");
}
Err(e) => return Err(e.into()),
Ok(r) => { /* use r */ }
} Prevention
- Keep skill files under a stable, version-controlled skills directory
- Point skills_dir at an absolute path that survives home-directory moves
- Re-check $CODEWHALE_HOME after environment or container changes
- Restore dotfiles/skills via your sync tool before launching the TUI
When it happens
Trigger: Invoking a skill (execute) whose Skill.path no longer exists — e.g. the skills_dir contents were deleted/moved after registration, or the resolved path from skills_dir/$CODEWHALE_HOME/home changed between sessions.
Common situations: Deleted or moved skills directory; config.toml `skills_dir` pointing at a path that no longer exists; $CODEWHALE_HOME changed; syncing tool (dotfiles manager) removed the file; invoking a skill in a fresh machine/container where the file wasn't copied.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- owned skill path does not exist
- plugin Agent component is unavailable
- audited owned root does not match mutation target
- audited skill path does not match owned package
- audited skill root identity changed; refusing mutation
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/1614eb75d6abd68f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tools/skill.rs:200
}
/// A native registry entry whose SKILL.md vanished from disk after discovery
/// (deleted, or resolved under a wrong home directory) must fail loudly with
/// the exact path — never silently serve the stale cached body while the user
/// believes the skill loaded (§2.5).
fn ensure_native_skill_file_present(skill: &Skill) -> Result<(), ToolError> {
if !matches!(skill.source, SkillSource::Native) || skill.path.is_file() {
return Ok(());
}
let message = format!(
"Skill `{}` is registered at {} but that file no longer exists on disk, \
so the skill did not load. Restore the file, or fix the skills directory it \
came from (`skills_dir` in config.toml, `$CODEWHALE_HOME`, or the OS home) — \
the path above shows exactly where the runtime looked.",
skill.name,
skill.path.display()
);
crate::logging::warn(&message);
Err(ToolError::execution_failed(message))
}
fn ensure_reviewed_plugin_skill_is_current(
skill: &Skill,
workspace: &std::path::Path,
) -> Result<(), ToolError> {
let SkillSource::Plugin {
plugin_name,
authority,
..
} = &skill.source
else {
return Ok(());
};
if authority.workspace != workspace {
return Err(ToolError::execution_failed(format!(View on GitHub (pinned to 73e0f67d83)