{"record":{"id":"ee9275c096880e06","repo":"jdx/mise","slug":"cannot-write-windows-launcher-because-is-not-a-ee9275","errorCode":null,"errorMessage":"cannot write Windows launcher because {} is not a regular file","messagePattern":"cannot write Windows launcher because (.+?) is not a regular file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/generate/task_stubs.rs","lineNumber":284,"sourceCode":"///\n/// The stub path is the user's choice, so `bin/<task>.cmd` is a name a project may already be\n/// using for a script of its own — and unlike the stub itself, nothing about the name says mise\n/// owns it. Checked during validation rather than at the write, so a launcher that is not ours\n/// stops the whole run instead of leaving a half-generated `bin/`.\nfn validate_launcher_path(stub: &TaskStub<'_>) -> Result<()> {\n    let Some(launcher) = super::windows_launcher_path(&stub.path) else {\n        return Ok(());\n    };\n    match fs::symlink_metadata(&launcher) {\n        Ok(metadata) if metadata.file_type().is_file() => {\n            if !super::is_generated_launcher(&file::read_to_string(&launcher)?) {\n                bail!(\n                    \"cannot write Windows launcher because {} is not a generated launcher\",\n                    display_path(&launcher)\n                );\n            }\n        }\n        Ok(_) => bail!(\n            \"cannot write Windows launcher because {} is not a regular file\",\n            display_path(&launcher)\n        ),\n        Err(err) if matches!(err.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) => {}\n        Err(err) => return Err(err.into()),\n    }\n    Ok(())\n}\n\nfn validate_generated_stub_directory(path: &Path, expected: &str, task: &Task) -> Result<()> {\n    let default = path.join(\"_default\");\n    match fs::symlink_metadata(&default) {\n        Ok(metadata)\n            if metadata.file_type().is_file() && file::read_to_string(&default)? == expected => {}\n        _ => bail!(\n            \"cannot replace task stub directory because {} does not contain the generated stub for task {}\",\n            display_path(path),\n            task.display_name","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/cli/generate/task_stubs.rs#L266-L302","documentation":"The Windows launcher path bin/<task>.cmd exists but is not a regular file (a directory, a symlink, or another special object). mise cannot write the launcher onto it, so validation fails before any stub is written.","triggerScenarios":"`mise generate task-stubs` when a directory or other non-file object is named bin/<task>.cmd — usually an accidental `mkdir bin/task.cmd` or a symlinked bin layout.","commonSituations":"Tools that create `<name>.cmd/` directories; misnamed folders; symlink farms under bin/.","solutions":["Remove the offending object: `rm -rf bin/<task>.cmd`","Rename the task so the sibling launcher path differs","Generate into another --dir that is clean"],"exampleFix":"# before\n$ ls -ld bin/build.cmd   # it is a directory\n$ mise generate task-stubs\n# error: bin/build.cmd is not a regular file\n\n# after\n$ rm -rf bin/build.cmd\n$ mise generate task-stubs","handlingStrategy":"type-guard","validationCode":"#!/bin/bash\nfor f in bin/*.cmd; do\n  [ -e \"$f\" ] && [ ! -f \"$f\" ] && { echo \"$f is not a regular file\" >&2; exit 1; }\ndone\nmise generate task-stubs","typeGuard":"launcher_path_free() {\n  # 0 when <stub>.cmd is absent or a regular file\n  [ ! -e \"$1.cmd\" ] || { [ -f \"$1.cmd\" ] && [ ! -L \"$1.cmd\" ]; }\n}","tryCatchPattern":null,"preventionTips":["Never create directories whose names end in .cmd inside the stub dir","Audit bin/ for odd objects before first generation in a repo"],"tags":["mise","task-stubs","windows","file-type","generate"],"backgroundTag":"unsupported-file-type","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}