{"record":{"id":"0803c16ed3ad0323","repo":"jdx/mise","slug":"cannot-create-task-stub-directory-because-is-no","errorCode":null,"errorMessage":"cannot create task stub directory because {} is not a directory","messagePattern":"cannot create task stub directory because (.+?) is not a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/generate/task_stubs.rs","lineNumber":560,"sourceCode":"                        \"cannot write task stub because {} is not a generated task stub\",\n                        display_path(&stub.path)\n                    );\n                }\n            }\n            Ok(_) => bail!(\n                \"cannot write task stub because {} is not a regular file\",\n                display_path(&stub.path)\n            ),\n            Err(err) if matches!(err.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) => {}\n            Err(err) => return Err(err.into()),\n        }\n        validate_launcher_path(stub, launchers)?;\n        for parent in stub.path.ancestors().skip(1) {\n            match fs::symlink_metadata(parent) {\n                Ok(metadata)\n                    if metadata.file_type().is_dir()\n                        || migrations.contains(&StubMigration::File(parent.to_path_buf())) => {}\n                Ok(_) => bail!(\n                    \"cannot create task stub directory because {} is not a directory\",\n                    display_path(parent)\n                ),\n                Err(err)\n                    if matches!(err.kind(), ErrorKind::NotFound | ErrorKind::NotADirectory) => {}\n                Err(err) => return Err(err.into()),\n            }\n            if parent == dir {\n                break;\n            }\n        }\n    }\n    Ok(migrations.into_iter().collect())\n}\n\n/// Refuse to replace a launcher beside a stub that mise did not write.\n///\n/// The stub path is the user's choice, so `bin/<task>.cmd` is a name a project may already be","sourceCodeStart":542,"sourceCodeEnd":578,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/cli/generate/task_stubs.rs#L542-L578","documentation":"When creating nested task stubs, mise walks every ancestor directory of each stub path and requires each to be a real directory (or a legacy stub file queued for migration into a directory). This error means an ancestor exists as a non-directory file, so the stub's directory structure cannot be created.","triggerScenarios":"Running `mise generate task-stubs` with nested stub paths where an intermediate path component exists as a regular file, e.g. a file named `.mise/tasks` or a file where a subdirectory like `tasks/build` is needed.","commonSituations":"A previously generated flat stub file occupies a path that nested layout now needs as a directory but which was not recognized as a migratable stub; users created a file with the same name as a planned subdirectory.","solutions":["Remove or rename the file occupying the intermediate path so mise can create the directory","Ensure the file is recognized as a legacy generated stub (its content must match generated output) so it gets migrated","Restructure task names/paths so nested components don't collide with existing files"],"exampleFix":"// before\n.mise/tasks/build  # regular file, but build/x needs build/ to be a directory\n// after\nrm .mise/tasks/build && mise generate task-stubs","handlingStrategy":"validation","validationCode":"for (const parent of ancestorsOf(stubPath)) {\n  const st = fs.lstatSync(parent, { throwIfNoEntry: false });\n  if (st && !st.isDirectory()) {\n    throw new Error(`${parent} blocks directory creation; remove or migrate it first`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  execSync('mise generate task-stubs');\n} catch (e) {\n  if (String(e).includes('is not a directory')) {\n    console.error('A path component exists as a file; remove/rename it and rerun');\n  }\n}","preventionTips":["Migrate to nested layouts in one step via mise's own migration rather than mixing layouts","Do not create files whose names collide with planned subdirectories","Run generation after pulling layout changes before committing"],"tags":["cli","task-stubs","filesystem","path-collision"],"backgroundTag":"path-is-not-a-directory","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"}