{"record":{"id":"0ae06de5c607c451","repo":"volta-cli/volta","slug":"filename-is-a-duplicate-of-executable-on","errorCode":null,"errorMessage":"filename `{}` is a duplicate of `{}` executable on non-Windows operating systems","messagePattern":"filename `(.+?)` is a duplicate of `(.+?)` executable on non-Windows operating systems","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"crates/volta-layout-macro/src/ast.rs","lineNumber":162,"sourceCode":"\n                    if filename.ends_with(\".exe\") || filename.ends_with(\"[.exe]\") {\n                        let error = syn::Error::new(\n                            prefix.filename.span(),\n                            \"the `.exe` extension is not allowed for directory names\",\n                        );\n                        return Err(error.to_compile_error());\n                    }\n\n                    if let Some(kind) = visited_entries.get(&filename) {\n                        let message = match kind {\n                            EntryKind::Exe => {\n                                format!(\"filename `{}` is a duplicate of `{}` executable on non-Windows operating systems\", filename, filename)\n                            }\n                            _ => {\n                                format!(\"duplicate filename `{}`\", filename)\n                            }\n                        };\n                        let error = syn::Error::new(prefix.filename.span(), message);\n                        return Err(error.to_compile_error());\n                    }\n\n                    visited_entries.insert(filename.clone(), EntryKind::Dir);\n\n                    results.dirs.push(entry);\n                    let mut sub_context = context.clone();\n                    sub_context.push(prefix.filename);\n                    dir.flatten(results, sub_context)?;\n                }\n                _ => {\n                    let filename = prefix.filename.value();\n                    if filename.ends_with(\"[.exe]\") {\n                        let filename = &filename[0..filename.len() - 6];\n\n                        if let Some(kind) = visited_entries.get(filename) {\n                            let message = match kind {\n                                EntryKind::Exe => {","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/volta-cli/volta/blob/5eedd5fb2f682baceb47a242289111fcd79435a5/crates/volta-layout-macro/src/ast.rs#L144-L180","documentation":"This is a compile-time error from the layout! proc macro: within one directory, every filename must be unique. The macro tracks each visited filename with an EntryKind; if a plain file or directory name collides with a name already declared as an `[.exe]` executable, it reports that the new filename is a duplicate of that executable (since on non-Windows the executable occupies the same `name`, and on Windows `name.exe`). A collision with a non-exe entry reports \"duplicate filename\".","triggerScenarios":"Declaring two entries with the same filename literal inside one layout! directory — specifically a file or dir entry whose name equals a previously declared `name[.exe]` executable entry, or any two entries sharing a name.","commonSituations":"Declaring both \"node\" and \"node[.exe]\" in the same directory; copy-pasting an entry and forgetting to rename it; merging layout blocks so the same tool is declared twice.","solutions":["Remove or rename the duplicate entry so each filename in the directory is unique","If a platform-specific executable was intended, keep only the single `name[.exe]` entry and delete the plain-named one","If both a file and executable with the same name are needed, they must live in different directories"],"exampleFix":"// before\n\"bin\": dir { \"node[.exe]\": file; \"node\": file; }\n// after\n\"bin\": dir { \"node[.exe]\": file; }","handlingStrategy":"validation","validationCode":"fn find_dup(names: &[&str]) -> Option<&str> {\n    let mut seen = std::collections::HashSet::new();\n    names.iter().find(|n| !seen.insert(strip_exe_marker(n)))\n}\nfn strip_exe_marker(n: &str) -> &str { n.strip_suffix(\"[.exe]\").unwrap_or(n) }","typeGuard":null,"tryCatchPattern":"// compile-time proc-macro error: no runtime catch. Pre-check literals for duplicates\n// (after stripping [.exe]) before committing layout! changes; cargo check in CI.","preventionTips":["Ensure each filename in a directory block is unique after stripping the [.exe] suffix","Never declare both \"name\" and \"name[.exe]\" in the same directory","Search the layout block for repeated string literals before compiling"],"tags":["proc-macro","compile-time","duplicate","rust"],"backgroundTag":"file-already-exists","analyzedSha":"5eedd5fb2f682baceb47a242289111fcd79435a5","analyzedAt":"2026-09-08T00:01:15.963Z","contentChangedAt":"2026-09-08T00:01:15.963Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}