santifer/career-ops · error · Error
targetDir is not an existing directory
Error message
targetDir is not an existing directory: ${targetDir} What it means
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.
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.
Example fix
// before
await seedFixture(tmpDir); // tmpDir never created
// after
fs.mkdirSync(tmpDir, { recursive: true });
await seedFixture(tmpDir); Defensive patterns
Strategy: validation
Validate before calling
import { mkdirSync, existsSync, statSync } from 'node:fs';
if (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) {
mkdirSync(targetDir, { recursive: true });
}
await seedFixture(targetDir, { state }); Type guard
const isExistingDirectory = (p) => existsSync(p) && statSync(p).isDirectory();
Try / catch
try {
await seedFixture(targetDir);
} catch (err) {
if (err.message.startsWith('targetDir is not an existing directory')) {
fs.mkdirSync(targetDir, { recursive: true });
await seedFixture(targetDir);
} else throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- apify: JD cache write failed for
- cannot read
- Could not release report reservation
- ⚠️ Could not release report reservation
- ⚠️ Could not release report reservation
AI-assisted analysis of santifer/career-ops@aac998c7ed (2026-09-16).
Data as JSON: /api/errors/7a413484381b3eea.
Report an issue: GitHub.
Appendix: source
Thrown at seed-fixture.mjs:67
// deliberately exempt). Leaving it in would make a whole second repository an
// allowlisted fixture state and seed it into the install under test (#3762).
return readdirSync(FIXTURES).sort()
.filter((n) => statSync(join(FIXTURES, n)).isDirectory() && !isNestedCheckout(join(FIXTURES, n)));
}
// Strict allowlist: a state must be one of the real fixture subdirectories.
// Membership in listStates() (basenames only) inherently rejects both unknown
// states and traversal strings ('../x', 'state/../..'), so no join() ever
// escapes FIXTURES.
function assertKnownState(state) {
const states = listStates();
if (!states.includes(state)) {
throw new Error(`Unknown fixture state: ${state} (have: ${states.join(', ') || 'none'})`);
}
}
export function seedFixture(targetDir, { state = DEFAULT_STATE } = {}) {
if (!existsSync(targetDir) || !statSync(targetDir).isDirectory()) throw new Error(`targetDir is not an existing directory: ${targetDir}`);
assertKnownState(state);
const src = join(FIXTURES, state);
// expected.json is harness metadata, not user data — never seed it.
const files = walk(src).filter((f) => f !== 'expected.json');
const manifest = {};
for (const f of files) {
const dest = join(targetDir, f);
mkdirSync(dirname(dest), { recursive: true });
cpSync(join(src, f), dest);
manifest[f] = createHash('sha256').update(readFileSync(dest)).digest('hex');
}
return { state, files, manifest };
}
export function loadExpectations(state = DEFAULT_STATE) {
assertKnownState(state);
return JSON.parse(readFileSync(join(FIXTURES, state, 'expected.json'), 'utf-8'));
}View on GitHub (pinned to aac998c7ed)