microsoft/typescript-go · error
Cannot create directory: a file already exists at "/${segmen
Error message
Cannot create directory: a file already exists at "/${segments.join("/")}" What it means
Thrown by ensureDirectory inside createVirtualFileSystem when inserting a file whose path needs a directory segment that is already registered as a file. The virtual FS is a tree built from the flat files map (and later writeFile callbacks from the server); if one path is both a file and a prefix of another path (e.g., "/a" and "/a/b.ts"), the tree cannot represent it and construction/write fails.
Source
Thrown at _packages/native-preview/src/api/fs.ts:86
return undefined;
}
const child: VNode = current.children[segment];
if (!child) {
return undefined;
}
current = child;
}
return current;
}
function ensureDirectory(segments: string[]): VDirectory {
let current: VDirectory = root;
for (const segment of segments) {
if (!current.children[segment]) {
current.children[segment] = { type: "directory", children: {} };
}
else if (current.children[segment].type !== "directory") {
throw new Error(`Cannot create directory: a file already exists at "/${segments.join("/")}"`);
}
current = current.children[segment] as VDirectory;
}
return current;
}
function addToTree(path: string): void {
const segments = getPathComponents(path).slice(1);
if (segments.length === 0) {
throw new Error(`Invalid file path: "${path}"`);
}
const filename = segments.pop()!;
const dirNode = ensureDirectory(segments);
dirNode.children[filename] = { type: "file" };
}
function writeFile(path: string, data: string): void {
content[path] = data;
View on GitHub (pinned to 1bcfa18d79)
Solutions
- Sanitize the files map before creating the virtual FS: remove entries whose path is also a prefix of another entry
- Normalize keys to absolute POSIX-style paths (forward slashes) so casing/separator differences do not create collisions
- When handling server writeFile callbacks, catch this error and reject/rename the conflicting virtual file deliberately
- Validate your fixture generator so directories and files never share the same path
Example fix
// before
const vfs = createVirtualFileSystem({
"/project/util": "...", // file
"/project/util/index.ts": "...", // util as directory -> throws
});
// after
const vfs = createVirtualFileSystem({
"/project/util.ts": "...",
"/project/util/index.ts": "...",
}); Defensive patterns
Strategy: validation
Validate before calling
// Reject file/directory path collisions before building the virtual FS
function hasPathCollision(files: Record<string, string>): string | undefined {
const paths = Object.keys(files).map(p => p.replace(/\\/g, '/')).sort();
for (let i = 0; i < paths.length - 1; i++) {
if (paths[i + 1].startsWith(paths[i].endsWith('/') ? paths[i] : paths[i] + '/')) return paths[i];
}
return undefined;
}
const collision = hasPathCollision(files);
if (collision) throw new Error(`'${collision}' is both a file and a directory prefix`);
const vfs = createVirtualFileSystem(files); Try / catch
try {
createVirtualFileSystem(files);
} catch (e) {
if (e instanceof Error && e.message.includes('a file already exists at')) {
// report the offending fixture entry and fix the data
console.error('Virtual FS collision:', e.message);
} else throw e;
} Prevention
- Normalize all virtual paths to absolute POSIX form with forward slashes
- Generate fixtures from a tree structure, not a flat map, so collisions are impossible
- Validate server writeFile callback paths for parent collisions before inserting
When it happens
Trigger: Passing a files map to createVirtualFileSystem containing both "/a" (file) and "/a/b.ts"; the Go server calling the writeFile callback with a path whose parent collides with an existing virtual file; inconsistent casing or separator styles (Windows backslashes) creating near-duplicate entries that collapse into collisions.
Common situations: In-memory test fixtures generated from real directory listings that include extensionless files doubling as directories; bundling virtual tarball-like inputs where a file and folder share a name; path strings built by joining user input without normalization.
Related errors
- Invalid file path: "${path}"
- Cannot run a temporary file update on an inactive snapshot
- Snapshot is disposed
- Bad line number. Line: ${line}, lineStarts.length: ${lineSta
- Expected ${pkgName} to declare exactly one bin entry named $
AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16).
Data as JSON: /api/errors/bd57dc90b39ea5af.
Report an issue: GitHub.