{"record":{"id":"5cac063825432e6f","repo":"jdx/mise","slug":"cannot-replace-task-stub-directory-because-is-n","errorCode":null,"errorMessage":"cannot replace task stub directory because {} is not a generated task stub","messagePattern":"cannot replace task stub directory because (.+?) is not a generated task stub","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/generate/task_stubs.rs","lineNumber":335,"sourceCode":"            let child_files = validate_generated_stub_tree(&entry_path)?;\n            if child_files == 0 {\n                bail!(\n                    \"cannot replace task stub directory because {} is empty\",\n                    display_path(&entry_path)\n                );\n            }\n            files += child_files;\n        } else if metadata.file_type().is_file()\n            && is_generated_task_stub(&file::read_to_string(&entry_path)?)\n        {\n            files += 1;\n        } else if metadata.file_type().is_file()\n            && super::is_generated_launcher(&file::read_to_string(&entry_path)?)\n        {\n            // Our own Windows launcher. Not counted towards `files`: a directory holding nothing\n            // but launchers has no stubs left and should still be reported as empty.\n        } else {\n            bail!(\n                \"cannot replace task stub directory because {} is not a generated task stub\",\n                display_path(&entry_path)\n            );\n        }\n    }\n    Ok(files)\n}\n\nfn is_generated_task_stub(contents: &str) -> bool {\n    let mut lines = contents.lines();\n    matches!(lines.next(), Some(\"#!/bin/sh\"))\n        && matches!(lines.next(), Some(\"# generated by mise task-stubs\"))\n        && lines\n            .next()\n            .and_then(|line| line.strip_prefix(\"exec \"))\n            .and_then(|line| line.strip_suffix(\" \\\"$@\\\"\"))\n            .is_some_and(|line| line.contains(\" run \"))\n        && lines.next().is_none()","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/cli/generate/task_stubs.rs#L317-L353","documentation":"Walking a stub directory mise intends to replace, an entry is neither a generated stub (first lines `#!/bin/sh` then `# generated by mise task-stubs`) nor a generated Windows launcher (`@echo off` + `rem generated by mise`). One foreign file means the directory is not purely mise's output, so mise refuses to replace it — deleting it could destroy user data.","triggerScenarios":"Any extra file inside bin/<parent>/ — notes, compiled artifacts, cache files, a hand script — while the nested-stub migration for that directory is pending.","commonSituations":"Build outputs written into bin/; developers storing scratch files under the stub directory; tools seeding .gitkeep-with-content.","solutions":["Move or remove the foreign file named in the error: `git rm bin/<parent>/<file>`","Rerun `mise generate task-stubs`","Keep build outputs out of the stub dir (.gitignore, out-of-tree build paths) so they do not return"],"exampleFix":"# before\n$ mise generate task-stubs\n# error: bin/build/notes.md is not a generated task stub\n\n# after\n$ git rm bin/build/notes.md\n$ mise generate task-stubs","handlingStrategy":"type-guard","validationCode":"#!/bin/bash\n# every file in a stub directory must be a generated stub or launcher\nwhile IFS= read -r -d '' f; do\n  is_mise_stub \"$f\" || is_mise_launcher \"$f\" || { echo \"foreign file: $f\" >&2; exit 1; }\ndone < <(find bin -type f -print0)\nmise generate task-stubs","typeGuard":"is_mise_stub() {\n  [ \"$(head -1 \"$1\")\" = '#!/bin/sh' ] && [ \"$(sed -n 2p \"$1\")\" = '# generated by mise task-stubs' ]\n}\nis_mise_launcher() {\n  [ \"$(head -1 \"$1\")\" = '@echo off' ] && [ \"$(sed -n 2p \"$1\")\" = 'rem generated by mise' ]\n}","tryCatchPattern":"if ! mise generate task-stubs; then\n  echo 'foreign file inside stub directory — move it out (e.g. to scripts/) and rerun' >&2\n  exit 1\nfi","preventionTips":["Keep build outputs, notes, and caches out of the stub directory (.gitignore them)","Treat any file under bin/<parent>/ that is not a stub or launcher as a bug in your build layout"],"tags":["mise","task-stubs","ownership","foreign-file","generate"],"backgroundTag":"generated-file-ownership-conflict","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}