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

  1. Restore the skill file at the exact path shown in the message (skill.path)
  2. 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
  3. 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

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


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)