{"record":{"id":"0959dcba373f90df","repo":"nanocoai/nanoclaw","slug":"shared-skill-not-symlinked-real-entry-occupies-th","errorCode":null,"errorMessage":"Shared skill not symlinked: real entry occupies the path (template overlay or stale pre-refactor copy)","messagePattern":"Shared skill not symlinked: real entry occupies the path \\(template overlay or stale pre-refactor copy\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/container-runner.ts","lineNumber":831,"sourceCode":"  }\n\n  // Create symlinks for desired skills (container path targets)\n  for (const skill of desired) {\n    const linkPath = path.join(skillsDir, skill);\n    let entry: fs.Stats | undefined;\n    try {\n      entry = fs.lstatSync(linkPath);\n    } catch {\n      /* missing */\n    }\n    if (!entry) {\n      fs.symlinkSync(`/app/skills/${skill}`, linkPath);\n    } else if (!entry.isSymbolicLink()) {\n      // A real entry here is either a template overlay (intentional; see\n      // src/group-skills.ts) or a stale pre-refactor skill copy that shadows\n      // the shared skill (#3001). No marker distinguishes them yet, so\n      // surface the skip instead of staying silent.\n      log.warn(\n        'Shared skill not symlinked: real entry occupies the path (template overlay or stale pre-refactor copy)',\n        {\n          skill,\n          path: linkPath,\n        },\n      );\n    }\n  }\n}\n\n/**\n * Resolve the group's skill selection to concrete names — `'all'` recomputes\n * from `container/skills/` so newly-added upstream skills appear automatically.\n */\nfunction selectedSkillNames(containerConfig: import('./container-config.js').ContainerConfig): string[] {\n  if (containerConfig.skills !== 'all') return containerConfig.skills;\n  const sharedSkillsDir = path.join(process.cwd(), 'container', 'skills');\n  return fs.existsSync(sharedSkillsDir)","sourceCodeStart":813,"sourceCodeEnd":849,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/container-runner.ts#L813-L849","documentation":"While syncing shared skills as symlinks into a group's skills directory, an existing real (non-symlink) entry occupies the path. This is either an intentional template overlay or a stale pre-refactor copy shadowing the shared skill (#3001); since no marker distinguishes them, the shared skill is skipped with a warning.","triggerScenarios":"`syncSkillSymlinks` (called from `buildMounts`) finds a real file/directory at `groups/<folder>/skills/<skill>` where a symlink to `/app/skills/<skill>` should go.","commonSituations":"A group created from a template that ships its own version of a shared skill; leftover skill copies from before the shared-mount refactor blocking updates to that skill.","solutions":["If the local copy is stale (pre-refactor), delete it: `rm -rf groups/<folder>/skills/<skill>` so the symlink is created","If it's an intentional template overlay, verify the local copy is current and ignore the warning","Diff the local copy against `container/skills/<skill>` to decide which case it is"],"exampleFix":"rm -rf groups/my-group/skills/agent-browser # stale copy; next spawn symlinks the shared skill","handlingStrategy":"validation","validationCode":"const entry = fs.lstatSync(linkPath, { throwIfNoEntry: false });\nif (entry && !entry.isSymbolicLink()) {\n  // decide: template overlay (keep) vs stale copy (delete) before spawning\n}","typeGuard":"function isStaleSkillCopy(p: string): boolean {\n  return fs.lstatSync(p).isSymbolicLink() === false && !isTemplateOverlay(p);\n}","tryCatchPattern":null,"preventionTips":["Keep group skills dirs clean after refactors; remove duplicated shared skills","Document which skills a template overlays","After group template changes, diff groups/<folder>/skills against container/skills"],"tags":["skills","symlink","container-mount","stale-state"],"backgroundTag":"path-occupied-by-existing-file","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}