{"record":{"id":"4a67845ed48b674e","repo":"jdx/mise","slug":"cannot-replace-task-stub-directory-because-is-e","errorCode":null,"errorMessage":"cannot replace task stub directory because {} is empty","messagePattern":"cannot replace task stub directory because (.+?) is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/generate/task_stubs.rs","lineNumber":636,"sourceCode":"            display_path(path),\n            task.display_name\n        ),\n    }\n\n    validate_generated_stub_tree(path, launchers)?;\n    Ok(())\n}\n\nfn validate_generated_stub_tree(path: &Path, launchers: &Launchers) -> Result<usize> {\n    let mut files = 0;\n    for entry in fs::read_dir(path)? {\n        let entry = entry?;\n        let entry_path = entry.path();\n        let metadata = fs::symlink_metadata(&entry_path)?;\n        if metadata.file_type().is_dir() {\n            let child_files = validate_generated_stub_tree(&entry_path, launchers)?;\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() && is_exe_path(&entry_path) {\n            // A native launcher of ours. Checked before anything reads the file as text, which a\n            // binary is not. Not counted towards `files`, same as the `.cmd`: a directory holding\n            // nothing but launchers has no stubs left and should still be reported as empty.\n            if !launchers.owns(&entry_path) {\n                bail!(\n                    \"cannot replace task stub directory because {} is not a generated task stub\",\n                    display_path(&entry_path)\n                );\n            }\n        } else if metadata.file_type().is_file()\n            && is_generated_task_stub(&file::read_to_string(&entry_path)?)\n        {","sourceCodeStart":618,"sourceCodeEnd":654,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/cli/generate/task_stubs.rs#L618-L654","documentation":"When replacing a generated stub directory, mise recursively validates its tree. Every subdirectory must contain at least one recognized file (a generated stub, or only mise launchers which count as empty). A subdirectory with no children at all, or one holding only launcher files so it has zero actual stub files, is treated as not a generated tree and mise refuses to proceed.","triggerScenarios":"Running `mise generate task-stubs` when a subdirectory inside an existing stub directory is empty, or contains only `.cmd`/native launchers with no generated stub files left.","commonSituations":"User deleted stub files but left empty directories behind; a failed/partial cleanup removed stubs but not launchers; copying the tasks tree with an incomplete sync tool.","solutions":["Delete the empty subdirectory (and any launcher-only directories), then re-run `mise generate task-stubs`.","Back up anything you want to keep from the stub directory tree and remove the whole directory to let mise regenerate.","Investigate why stubs vanished (partial deletion, sync conflict) before regenerating."],"exampleFix":"// before: .mise/tasks/build/legacy/ is an empty dir\nrm -rf .mise/tasks/build/legacy\nmise generate task-stubs\n// after: directory replaced cleanly","handlingStrategy":"validation","validationCode":"for sub in Path('.mise/tasks/build').rglob('*'):\n    if sub.is_dir() and not any(sub.iterdir()):\n        print(f\"empty subdirectory {sub} will block stub regeneration\")","typeGuard":"def no_empty_subdirs(d: Path) -> bool:\n    return all(any(sub.iterdir()) for sub in d.rglob('*') if sub.is_dir())","tryCatchPattern":null,"preventionTips":["Delete empty directories when removing generated stubs, not just the files","Use mise's own removal/regeneration flow instead of partial manual deletes","Verify complete syncs when copying tasks trees between machines"],"tags":["filesystem","task-stubs","directory","validation"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}