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

  1. Sanitize the files map before creating the virtual FS: remove entries whose path is also a prefix of another entry
  2. Normalize keys to absolute POSIX-style paths (forward slashes) so casing/separator differences do not create collisions
  3. When handling server writeFile callbacks, catch this error and reject/rename the conflicting virtual file deliberately
  4. 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

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


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/bd57dc90b39ea5af. Report an issue: GitHub.