{"record":{"id":"64dcc5e99831a462","repo":"jdx/mise","slug":"cannot-write-task-stub-because-is-a-symbolic-li","errorCode":null,"errorMessage":"cannot write task stub because {} is a symbolic link","messagePattern":"cannot write task stub because (.+?) is a symbolic link","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/generate/task_stubs.rs","lineNumber":533,"sourceCode":"                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 {\n        match fs::symlink_metadata(&stub.path) {\n            Ok(metadata) if metadata.file_type().is_dir() => {\n                validate_generated_stub_directory(&stub.path, &stub.output, stub.task, launchers)?;\n                migrations.insert(StubMigration::Directory(stub.path.clone()));\n            }\n            Ok(metadata) if metadata.file_type().is_symlink() => bail!(\n                \"cannot write task stub because {} is a symbolic link\",\n                display_path(&stub.path)\n            ),\n            Ok(metadata) if metadata.file_type().is_file() => {\n                let existing = file::read_to_string(&stub.path)?;\n                let legacy_leaf = stub.legacy_path == stub.path && existing == stub.legacy_output;\n                if existing != stub.output && !legacy_leaf {\n                    bail!(\n                        \"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) => {}","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/cli/generate/task_stubs.rs#L515-L551","documentation":"mise refuses to write a task stub if the target path is currently a symbolic link. Stub files are generated artifacts that mise manages directly; writing through an arbitrary symlink could modify an unintended file elsewhere, so it fails closed instead.","triggerScenarios":"Running `mise generate task-stubs` where an expected stub path (e.g. .mise/tasks/foo) is a symlink — often left by a user linking to a script elsewhere or by an earlier manual setup.","commonSituations":"Developers symlinked task scripts into the tasks directory; dotfile managers (stow, chezmoi) replaced task files with symlinks; old setups predating stub generation.","solutions":["Remove the symlink at the stub path so mise can write a real file","Replace the symlink with an actual copy of the target script if it must live in the tasks directory","Keep the symlink but exclude it from stub generation by renaming/relocating the task"],"exampleFix":"// before\n.mise/tasks/build -> ~/scripts/build.sh\n// after\nrm .mise/tasks/build && cp ~/scripts/build.sh .mise/tasks/build && mise generate task-stubs","handlingStrategy":"validation","validationCode":"const st = fs.lstatSync(stubPath, { throwIfNoEntry: false });\nif (st?.isSymbolicLink()) {\n  throw new Error(`${stubPath} is a symlink; mise generate task-stubs will refuse it`);\n}","typeGuard":"const isSymlink = (p: string): boolean => {\n  const st = fs.lstatSync(p, { throwIfNoEntry: false });\n  return !!st?.isSymbolicLink();\n};","tryCatchPattern":"try {\n  execSync('mise generate task-stubs');\n} catch (e) {\n  if (String(e).includes('is a symbolic link')) {\n    console.error('Replace the symlink with a real copy or remove it, then rerun');\n  }\n}","preventionTips":["Copy task scripts into the tasks directory instead of symlinking them","Configure dotfile managers (stow/chezmoi) to skip the tasks directory","Check for symlinks before committing generated stub layouts"],"tags":["cli","task-stubs","symlink"],"backgroundTag":"unsupported-operation","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"}