Hmbown/CodeWhale · error · anyhow::Error

refusing to copy symlink {}

Error message

refusing to copy symlink {}

What it means

Raised in copy_dir_regular_files during a skill package copy when a directory entry is a symlink. The copier only walks regular files and directories; a symlink in the source would either duplicate content outside the package or break the digest guarantees, so copying fails closed.

Source

Thrown at crates/tui/src/skills/mutation.rs:831

        outcome: SkillMutationOutcome::Imported,
    })
}

fn copy_skill_package(src: &Path, dest: &Path) -> Result<()> {
    // Fail closed: source must already pass package digest (no symlinks).
    package_digest::compute_package_digest(src).context("source package is not safe to copy")?;
    copy_dir_regular_files(src, dest)?;
    Ok(())
}

fn copy_dir_regular_files(src: &Path, dest: &Path) -> Result<()> {
    fs::create_dir_all(dest)?;
    for entry in fs::read_dir(src)? {
        let entry = entry?;
        let path = entry.path();
        let meta = fs::symlink_metadata(&path)?;
        if meta.file_type().is_symlink() {
            bail!("refusing to copy symlink {}", path.display());
        }
        let name = entry.file_name();
        let name_str = name.to_string_lossy();
        if name_str == install::INSTALLED_FROM_MARKER
            || name_str == install::TRUSTED_MARKER
            || name_str == ".system-installed-version"
        {
            continue;
        }
        let target = dest.join(&name);
        if meta.is_dir() {
            if name_str.starts_with('.') {
                continue;
            }
            copy_dir_regular_files(&path, &target)?;
        } else if meta.is_file() {
            if name_str.starts_with('.') {
                continue;

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Replace symlinks in the skill package with regular files or directories
  2. Re-audit the source package; compute_package_digest should have rejected it, so the package was modified after audit
  3. Re-install the external skill package from a clean source
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/tui/src/skills/mutation.rs:831 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/5069082bcae3ea5b. Report an issue: GitHub.