{"record":{"id":"1a8c342e960f6a10","repo":"pbakaus/impeccable","slug":"nothing-was-linked-because-matching-skill-folders","errorCode":null,"errorMessage":"Nothing was linked because matching skill folders already exist.","messagePattern":"Nothing was linked because matching skill folders already exist\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/skills/src/commands.rs","lineNumber":491,"sourceCode":"    if !yes {\n        out(io, &format!(\"Source checkout: {}\", source.checkout_root));\n        out(io, &format!(\"Target harness folder(s): {}\", targets.join(\", \")));\n        let ans = prompt.ask(io, &format!(\"Link impeccable skills into {} folder(s)? (Y/n) \", targets.len()))?;\n        if ans == \"n\" || ans == \"no\" {\n            out(io, \"Aborted. Re-run with --providers=<names> to choose explicitly (e.g. --providers=claude,cursor).\");\n            return Err(Flow::Exit(0));\n        }\n    }\n    let result = bundle::link_provider_skills(io, &source.bundle_root, &root, &targets, force).map_err(Flow::Throw)?;\n    // Linked installs are excluded from install/update refreshes (overwriting\n    // a symlink would destroy the link), so this is the only path that can\n    // deliver the OpenCode command bridge to them. A copy, not a symlink: the\n    // bridge is static and OpenCode scans the real commands dir. No-ops when\n    // the source checkout has no built commands (#483).\n    bundle::copy_provider_commands(&sys, &source.bundle_root, &root, &targets, Some(Scope::Project));\n    if result.linked == 0 && result.already == 0 {\n        if result.skipped > 0 {\n            err(io, \"Nothing was linked because matching skill folders already exist.\");\n            err(io, \"Existing skills were left untouched. Re-run with --force to replace them with links.\");\n        } else {\n            err(io, &format!(\"Nothing was linked: {} had no variants for {}.\", source.bundle_root, targets.join(\", \")));\n        }\n        return Err(Flow::Exit(1));\n    }\n    // Linked skill dirs resolve into the source checkout; repair the\n    // launcher/binary executable bit there too (through the symlink), so a\n    // checkout whose copier dropped modes still runs.\n    for provider in &targets {\n        let skills_dir = util::jsp::join(&[&root, provider, \"skills\"]);\n        for skill in util::read_dir_names(&skills_dir).unwrap_or_default() {\n            let dir = util::jsp::join(&[&skills_dir, &skill]);\n            if util::is_dir(&dir) {\n                crate::engine_binary::ensure_executable_scripts(&dir);\n            }\n        }\n    }","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/crates/skills/src/commands.rs#L473-L509","documentation":"After linking, if zero skills were linked and zero already existed, and some were skipped because matching skill folders already exist, the command fails with this message and exit code 1. The existing skills were deliberately left untouched.","triggerScenarios":"Running `impeccable link` when every candidate skill name already has a folder in the target harness directory (non-linked copies).","commonSituations":"Re-running link after a previous copy-based install; users want links but real folders shadow them.","solutions":["Re-run with `--force` to replace existing folders with links","Manually remove the existing skill folders and re-run `link`"],"exampleFix":"// before\nimpeccable link --providers=claude\n// after\nimpeccable link --providers=claude --force","handlingStrategy":"validation","validationCode":"const existing = fs.existsSync(path.join(target, 'skills', skillName));\nif (existing && !force) console.error('Skill exists; use --force to link over it');","typeGuard":null,"tryCatchPattern":"try { await link(); } catch (e) { if (/already exist/.test(String(e))) { console.error('Re-run with --force'); } }","preventionTips":["Check for existing skill folders before linking","Decide up front whether you want copies or links and stick with one","Use --force deliberately after reviewing existing skills"],"tags":["cli","link","conflict"],"backgroundTag":"file-already-exists","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}