{"record":{"id":"23ab971e5c6c45a6","repo":"Fission-AI/OpenSpec","slug":"refusing-to-generate-unsafe-skill-directory-name","errorCode":null,"errorMessage":"Refusing to generate: unsafe skill directory name ${JSON.stringify(dirName)}","messagePattern":"Refusing to generate: unsafe skill directory name (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/skillssh-shared.mjs","lineNumber":52,"sourceCode":"        `Refusing to generate: ${join(outDir, entry.name)} is a symlink. Remove it and re-run.`\n      );\n    }\n  }\n  for (const entry of entries) {\n    if (entry.isDirectory()) {\n      rmSync(join(outDir, entry.name), { recursive: true, force: true });\n    }\n  }\n}\n\n/**\n * Create `<outDir>/<dirName>` and return its path, guaranteeing the write\n * target is a real directory contained in outDir — never a path-traversing\n * name and never a symlink that would redirect the write elsewhere.\n */\nexport function prepareSkillDirectory(outDir, dirName) {\n  if (!/^[a-z0-9][a-z0-9-]*$/.test(dirName)) {\n    throw new Error(`Refusing to generate: unsafe skill directory name ${JSON.stringify(dirName)}`);\n  }\n  const skillDir = join(outDir, dirName);\n  mkdirSync(skillDir, { recursive: true });\n  if (!lstatSync(skillDir).isDirectory()) {\n    throw new Error(`Refusing to write through ${skillDir}: not a real directory.`);\n  }\n  return skillDir;\n}\n","sourceCodeStart":34,"sourceCodeEnd":61,"githubUrl":"https://github.com/Fission-AI/OpenSpec/blob/6926ccb18afa4ff621112813e9968334576ee11a/scripts/skillssh-shared.mjs#L34-L61","documentation":"Error \"Refusing to generate: unsafe skill directory name ${JSON.stringify(dirName)}\" thrown in Fission-AI/OpenSpec.","triggerScenarios":"Thrown at scripts/skillssh-shared.mjs:52 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"6926ccb18afa4ff621112813e9968334576ee11a","analyzedAt":"2026-08-25T12:29:45.729Z","schemaVersion":2},"datasetVersion":"2026-08-25T16:17:27.014Z"}