{"record":{"id":"7a413484381b3eea","repo":"santifer/career-ops","slug":"targetdir-is-not-an-existing-directory-targetdir","errorCode":null,"errorMessage":"targetDir is not an existing directory: ${targetDir}","messagePattern":"targetDir is not an existing directory: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"seed-fixture.mjs","lineNumber":67,"sourceCode":"  // deliberately exempt). Leaving it in would make a whole second repository an\n  // allowlisted fixture state and seed it into the install under test (#3762).\n  return readdirSync(FIXTURES).sort()\n    .filter((n) => statSync(join(FIXTURES, n)).isDirectory() && !isNestedCheckout(join(FIXTURES, n)));\n}\n\n// Strict allowlist: a state must be one of the real fixture subdirectories.\n// Membership in listStates() (basenames only) inherently rejects both unknown\n// states and traversal strings ('../x', 'state/../..'), so no join() ever\n// escapes FIXTURES.\nfunction assertKnownState(state) {\n  const states = listStates();\n  if (!states.includes(state)) {\n    throw new Error(`Unknown fixture state: ${state} (have: ${states.join(', ') || 'none'})`);\n  }\n}\n\nexport function seedFixture(targetDir, { state = DEFAULT_STATE } = {}) {\n  if (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) throw new Error(`targetDir is not an existing directory: ${targetDir}`);\n  assertKnownState(state);\n  const src = join(FIXTURES, state);\n  // expected.json is harness metadata, not user data — never seed it.\n  const files = walk(src).filter((f) => f !== 'expected.json');\n  const manifest = {};\n  for (const f of files) {\n    const dest = join(targetDir, f);\n    mkdirSync(dirname(dest), { recursive: true });\n    cpSync(join(src, f), dest);\n    manifest[f] = createHash('sha256').update(readFileSync(dest)).digest('hex');\n  }\n  return { state, files, manifest };\n}\n\nexport function loadExpectations(state = DEFAULT_STATE) {\n  assertKnownState(state);\n  return JSON.parse(readFileSync(join(FIXTURES, state, 'expected.json'), 'utf-8'));\n}","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/seed-fixture.mjs#L49-L85","documentation":"seedFixture() requires targetDir to be an existing directory and throws this when the path does not exist or statSync shows it is not a directory (e.g. a file). The function deliberately does not create directories; callers must provision the target first.","triggerScenarios":"seedFixture('/nonexistent/path') (directory never created); seedFixture('/tmp/a-file.txt') (path is a regular file); a race where another process deleted the directory between checks; a typo'd or relative-to-wrong-cwd path.","commonSituations":"Test setup forgetting fs.mkdir(tempDir, {recursive:true}) before seeding; pointing at a scratch file instead of a directory; temp-dir cleanup running concurrently with seeding; using a path relative to a different working directory in CI.","solutions":["Create the directory before calling: fs.mkdirSync(targetDir, { recursive: true }).","Confirm the path is a directory, not a file: fs.statSync(targetDir).isDirectory().","Use a per-test fresh temp dir (fs.mkdtempSync(path.join(os.tmpdir(), 'fixture-'))).","Resolve relative paths against a known base (path.resolve(__dirname, ...)) to avoid cwd surprises."],"exampleFix":"// before\nawait seedFixture(tmpDir); // tmpDir never created\n// after\nfs.mkdirSync(tmpDir, { recursive: true });\nawait seedFixture(tmpDir);","handlingStrategy":"validation","validationCode":"import { mkdirSync, existsSync, statSync } from 'node:fs';\nif (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) {\n  mkdirSync(targetDir, { recursive: true });\n}\nawait seedFixture(targetDir, { state });","typeGuard":"const isExistingDirectory = (p) => existsSync(p) && statSync(p).isDirectory();","tryCatchPattern":"try {\n  await seedFixture(targetDir);\n} catch (err) {\n  if (err.message.startsWith('targetDir is not an existing directory')) {\n    fs.mkdirSync(targetDir, { recursive: true });\n    await seedFixture(targetDir);\n  } else throw err;\n}","preventionTips":["Always create the target with mkdirSync(dir, { recursive: true }) before seeding — seedFixture never mkdirs.","Use fs.mkdtempSync() for per-test temporary directories to avoid collisions and stale paths.","Assert the path is a directory (not a file) when the target comes from configuration or CLI input.","In CI, resolve target paths against a known base directory to eliminate cwd dependence."],"tags":["filesystem","fixtures","argument-validation"],"backgroundTag":"directory-not-found","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}