volta-cli/volta · error · syn::Error
the `.exe` extension is not allowed for directory names
Error message
the `.exe` extension is not allowed for directory names
What it means
This is a compile-time error from the layout! proc macro. Within a layout! declaration, the `[.exe]` suffix marks an entry whose on-disk name is `name` on Windows and `name.exe` elsewhere; a directory whose name literally ends in `.exe` (or `[.exe]`) is therefore rejected, since Volta's layout models executables, not directories, with those names. The macro emits a syn compile error pointing at the offending string literal.
Solutions
- Remove the ".exe" / "[.exe]" suffix from the directory's filename literal in the layout! block
- If a nested executable was intended, declare it as a file entry with the `[.exe]` suffix instead of a braced directory
- Rename the directory so its name does not end in .exe
Example fix
// before
"bin/tools[.exe]": dir { ... }
// after
"bin/tools": dir { "shim[.exe]": file; } Defensive patterns
Strategy: validation
Validate before calling
fn valid_dir_name(name: &str) -> bool { !name.ends_with(".exe") && !name.ends_with("[.exe]") }
// check every directory literal in the layout! block before compiling Try / catch
// proc-macro compile error: fix the source; no runtime catch applies. // In CI, fail fast with: cargo check 2>&1 | grep 'not allowed for directory names'
Prevention
- Reserve the .exe / [.exe] suffixes for executable file entries only
- Never end directory name literals with .exe or [.exe] in layout! blocks
- Review Windows-specific layout templates when adapting them for directories
When it happens
Trigger: Declaring a directory entry in a layout! invocation whose filename literal ends with ".exe" or "[.exe]", e.g. `"tools/.exe": dir { ... }` or `"bin/tools[.exe]": dir { ... }`.
Common situations: Copy-pasting a Windows executable layout and mistakenly giving the directory the .exe name; confusing the `[.exe]` marker syntax (which belongs on executables) with directory entries; typos placing the marker on the wrong field.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- filename ` ` is a duplicate of ` ` executable on…
- executable ` ` (on non-Windows operating systems) is a…
- Could not determine directory information for
AI-assisted analysis of volta-cli/volta@5eedd5fb2f (2026-09-08).
Data as JSON: /api/errors/cebf0e529cba221a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/volta-layout-macro/src/ast.rs:146
/// Lowers the directory to a flattened intermediate representation.
fn flatten(self, results: &mut Ir, context: Vec<LitStr>) -> Result<()> {
let mut visited_entries = HashMap::new();
for pair in self.entries.into_pairs() {
let (prefix, punc) = pair.into_tuple();
let mut entry = Entry {
name: prefix.name,
context: context.clone(),
filename: prefix.filename.clone(),
};
match punc {
Some(FieldContents::Dir(dir)) => {
let filename = prefix.filename.value();
if filename.ends_with(".exe") || filename.ends_with("[.exe]") {
let error = syn::Error::new(
prefix.filename.span(),
"the `.exe` extension is not allowed for directory names",
);
return Err(error.to_compile_error());
}
if let Some(kind) = visited_entries.get(&filename) {
let message = match kind {
EntryKind::Exe => {
format!("filename `{}` is a duplicate of `{}` executable on non-Windows operating systems", filename, filename)
}
_ => {
format!("duplicate filename `{}`", filename)
}
};
let error = syn::Error::new(prefix.filename.span(), message);
return Err(error.to_compile_error());
}View on GitHub (pinned to 5eedd5fb2f)