windmill-labs/windmill · warning
Found ${collisions.length} path(s) that differ only by lette
Error message
Found ${collisions.length} path(s) that differ only by letter case:
${groups}
On case-insensitive filesystems (Windows, default macOS) these collapse into a single file/directory and cannot both be synced. Rename one side to a distinct path to make the tree sync reliably across platforms. What it means
A warning from warnUnrepresentableCaseCollisions during sync. The remote workspace contains two or more paths that differ only by letter case (e.g. `Scripts/Foo` and `scripts/foo`). On a case-insensitive filesystem (Windows, default macOS) these collapse into one file, so both cannot be synced to disk; the user must rename one.
Source
Thrown at cli/src/commands/sync/sync.ts:2487
const fromPrefix = fromSegs.slice(0, i + 1).join("/");
const toPrefix = toSegs.slice(0, i + 1).join("/");
const key = `${fromPrefix} -> ${toPrefix}`;
if (!seen.has(key)) {
seen.add(key);
out.push(key);
}
}
return out;
}
// Emit a single grouped warning for case-only collisions that cannot be
// represented on a case-insensitive filesystem (two distinct server paths
// differing only by case). Unlike the drift handled by
// canonicalizeCaseInsensitiveKeys, these require the user to rename one side.
function warnUnrepresentableCaseCollisions(collisions: string[][]): void {
if (collisions.length === 0) return;
const groups = collisions.map((g) => ` - ${g.join(" <-> ")}`).join("\n");
log.warn(
`Found ${collisions.length} path(s) that differ only by letter case:\n` +
`${groups}\n` +
`On case-insensitive filesystems (Windows, default macOS) these collapse ` +
`into a single file/directory and cannot both be synced. Rename one side ` +
`to a distinct path to make the tree sync reliably across platforms.`,
);
}
// Probe (and cache) whether `dir` lives on a case-insensitive filesystem.
// Auto-detected by round-tripping a probe file under two casings, with an
// explicit WMILL_CASE_INSENSITIVE_FS=true/false override so Windows behaviour
// can be forced (or emulated for cross-platform repos / tests) on any host.
let _caseInsensitiveFsCache: boolean | undefined;
export async function isCaseInsensitiveFilesystem(
dir: string,
): Promise<boolean> {
const override = (process.env.WMILL_CASE_INSENSITIVE_FS ?? "")
.trim()View on GitHub (pinned to e474e8803c)
Solutions
- Rename one of the colliding items on the server (via UI or `wmill` rename) so paths differ beyond case.
- Re-run the sync; the warning disappears once no case-only collisions remain.
- Prevent recurrence by adopting a naming convention (e.g. lowercase kebab-case paths) enforced in review/CI.
- On macOS, if the files already collapsed locally, delete the merged directory and re-pull after fixing the server paths.
Example fix
// before: server has both u/admin/hello_script.script/script u/admin/Hello_Script.script/script // after: rename one side u/admin/hello_script.script/script u/admin/hello_script_v2.script/script
Defensive patterns
Strategy: validation
Validate before calling
const seen = new Map<string, string>();
for (const p of allRemotePaths) {
const key = p.toLowerCase();
if (seen.has(key)) throw new Error(`Case collision: ${seen.get(key)} <-> ${p}`);
seen.set(key, p);
} Type guard
function hasCaseCollision(paths: string[]): boolean {
const set = new Set(paths.map(p => p.toLowerCase()));
return set.size !== paths.length;
} Try / catch
if (hasCaseCollision(remotePaths)) {
console.error("Rename one side on the server before pulling on case-insensitive OS");
} else {
await wmill.sync.pull(...);
} Prevention
- Adopt an all-lowercase naming convention for script/flow/folder paths.
- Run a case-collision lint in CI before syncing to case-insensitive dev machines.
- After case-only renames on the server, delete the collapsed local dir and re-pull.
- Develop on a case-sensitive filesystem (or APFS case-sensitive volume) for parity with Linux servers.
When it happens
Trigger: `wmill sync pull`/`push` detects, after diffing, remote item groups whose paths collide case-insensitively. Typical origin: items created by different people/automation with differing casing, or renames that only changed case.
Common situations: Team members on case-sensitive Linux created both paths; a rename on the server changed only letter case; duplicate scripts created with 'MyScript' vs 'myscript'; CI on Windows/macOS then fails or clobbers files when pulling.
Related errors
- Workspace folder not found, are you in the right directory?
- Error reading dir: ${localP}, ${e}
- File not found: ${filePath}
- Directory not found: ${targetDirectory}
- Path is not a directory: ${targetDirectory}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/a517e04465d07633.
Report an issue: GitHub.