{"record":{"id":"9f4910f2fb39bc9a","repo":"jdx/mise","slug":"cannot-create-nested-task-stubs-because-is-not","errorCode":null,"errorMessage":"cannot create nested task stubs because {} is not the generated stub for task {}","messagePattern":"cannot create nested task stubs because (.+?) is not the generated stub for task (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/generate/task_stubs.rs","lineNumber":198,"sourceCode":"    for path in &paths {\n        if !seen.insert(path) {\n            bail!(\n                \"multiple tasks map to task stub path {}\",\n                display_path(path)\n            );\n        }\n    }\n    Ok(paths)\n}\n\nfn validate_stub_paths(dir: &Path, stubs: &[TaskStub<'_>]) -> Result<Vec<StubMigration>> {\n    let mut migrations = HashSet::new();\n    for stub in stubs.iter().filter(|stub| stub.legacy_path != stub.path) {\n        match fs::symlink_metadata(&stub.legacy_path) {\n            Ok(metadata) if metadata.file_type().is_file() => {\n                let existing = file::read_to_string(&stub.legacy_path)?;\n                if existing != stub.output && existing != stub.legacy_output {\n                    bail!(\n                        \"cannot create nested task stubs because {} is not the generated stub for task {}\",\n                        display_path(&stub.legacy_path),\n                        stub.task.display_name\n                    );\n                }\n                migrations.insert(StubMigration::File(stub.legacy_path.clone()));\n            }\n            Ok(metadata) if metadata.file_type().is_dir() => {}\n            Ok(_) => bail!(\n                \"cannot create nested task stubs because {} is not a directory\",\n                display_path(&stub.legacy_path)\n            ),\n            Err(err) if matches!(err.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) => {}\n            Err(err) => return Err(err.into()),\n        }\n    }\n\n    for stub in stubs {","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/cli/generate/task_stubs.rs#L180-L216","documentation":"For a task whose stub location changed (parent task now written to `<parent>/_default`), mise migrates away the file at the old flat path — but only after proving it is its own: the content must equal the current stub (`#!/bin/sh` + `# generated by mise task-stubs` + exec line) or the legacy one (same, without the marker line). It matches neither, so mise treats it as the user's file and refuses to overwrite it.","triggerScenarios":"bin/<legacy path> is a hand-edited stub (someone customized the previously generated script) or an unrelated project script that happens to sit at the legacy path, and a run of `mise generate task-stubs` now wants the nested layout.","commonSituations":"Repo upgraded mise after contributors edited generated stubs; a pre-mise build script named identically to a new task.","solutions":["Inspect the file (`cat bin/<legacy path>`); if it holds custom logic you need, move it into the task definition (mise.toml [tasks] or tasks/*.toml) instead of the stub","If it is disposable or stale, remove it: `git rm bin/<legacy path>` and rerun `mise generate task-stubs`","If the name is load-bearing, rename the task so the paths stop colliding"],"exampleFix":"# before: bin/build was hand-edited after generation\n$ mise generate task-stubs\n# error: cannot create nested task stubs because bin/build is not the generated stub for task build\n\n# after\n$ git rm bin/build\n$ mise generate task-stubs   # writes bin/build/_default fresh","handlingStrategy":"validation","validationCode":"#!/bin/bash\n# refuse to migrate over a file mise cannot recognize as its own stub\nfor f in bin/*; do\n  [ -f \"$f\" ] || continue\n  if [ -x \"$f\" ] && ! sed -n '2p' \"$f\" | grep -q 'generated by mise task-stubs' \\\n     && ! head -1 \"$f\" | grep -q '^#!/bin/sh'; then\n    : # unrelated script — presence is fine, mise will refuse only if it occupies a legacy stub path\n  fi\ndone\nmise generate task-stubs","typeGuard":"is_mise_stub() {\n  # generated stubs start: #!/bin/sh then '# generated by mise task-stubs'\n  [ \"$(head -1 \"$1\")\" = '#!/bin/sh' ] && [ \"$(sed -n 2p \"$1\")\" = '# generated by mise task-stubs' ]\n}","tryCatchPattern":"if ! mise generate task-stubs; then\n  echo 'a file under bin/ is not a generated stub — inspect, then git rm it' >&2\n  exit 1\nfi","preventionTips":["Never hand-edit generated stubs; put changes in the task definition and regenerate","Treat bin/ as mise-owned output; keep project scripts in scripts/ instead","Commit stubs from a single canonical run (fixed --mise-bin) so regeneration always recognizes them"],"tags":["mise","task-stubs","migration","ownership","generate"],"backgroundTag":"generated-file-ownership-conflict","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}