{"record":{"id":"a385fac14f773f5a","repo":"jdx/mise","slug":"cannot-replace-task-stub-directory-because-does","errorCode":null,"errorMessage":"cannot replace task stub directory because {} does not contain the generated stub for task {}","messagePattern":"cannot replace task stub directory because (.+?) does not contain the generated stub for task (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/generate/task_stubs.rs","lineNumber":616,"sourceCode":"            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(\n    path: &Path,\n    expected: &str,\n    task: &Task,\n    launchers: &Launchers,\n) -> 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\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)?;","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/cli/generate/task_stubs.rs#L598-L634","documentation":"When `mise generate task-stub` replaces an entire stub directory, it first verifies the `_default` stub inside matches the expected generated content. If the directory has no readable `_default` file whose content equals the generated default stub, mise refuses to replace the directory and throws this error naming the task. This guards against wiping directories that contain user-owned content.","triggerScenarios":"Running `mise generate task-stub` targeting a directory that: lacks a `_default` child, has `_default` as a non-file (symlink/dir), or whose `_default` content differs from the freshly generated default stub text (edited or produced by an older mise version).","commonSituations":"Users hand-edited `_default`; a stub was generated by an older mise with different template text; a symlink farm (e.g. dotfiles manager) replaced `_default` with a symlink.","solutions":["Regenerate stubs into a clean directory instead of replacing the existing one","Restore the unmodified generated `_default` file (recreate via mise) before replacing the directory","Back up and remove the directory manually, then re-run `mise generate task-stub`"],"exampleFix":"// before: hand-edited _default diverges from generated content\n// stubs\\_default edited by hand -> replacement blocked\n// after: regenerate from scratch\nrm -r stubs\nmise generate task-stub --task build --output stubs","handlingStrategy":"validation","validationCode":"const def = path.join(stubDir, '_default');\nif (!fs.existsSync(def) || fs.lstatSync(def).isSymbolicLink()) {\n  throw new Error('stub directory lacks a plain generated _default; regenerate into a clean dir');\n}","typeGuard":"const hasPlainDefault = (dir: string): boolean => {\n  try { return fs.lstatSync(path.join(dir, '_default')).isFile(); } catch { return false; }\n};","tryCatchPattern":"try {\n  await exec('mise generate task-stub ...');\n} catch (e) {\n  if (String(e).includes('does not contain the generated stub')) {\n    fs.rmSync(stubDir, { recursive: true });\n    await exec('mise generate task-stub ...'); // regenerate fresh\n  }\n}","preventionTips":["Never hand-edit generated `_default` stubs","Regenerate stubs after mise version upgrades since templates may change","Avoid symlink managers over stub directories"],"tags":["windows","task-stub","validation","cli"],"backgroundTag":"unexpected-response-shape","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}