{"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":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/generate/task_stubs.rs","lineNumber":222,"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)?;\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":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/cli/generate/task_stubs.rs#L204-L240","documentation":"The target stub path (bin/<task> or bin/<parent>/_default) is a symbolic link. Writing through a symlink would modify whatever it points at, which mise cannot treat as its own output, so generation stops and names the link.","triggerScenarios":"`mise generate task-stubs` when bin/<task> is a symlink to elsewhere — e.g. a repo still using the bin/-full-of-symlinks convention (bin/foo -> ../tools/foo).","commonSituations":"Migrating a repo from symlink-style bin/ dispatch to committed stubs; contributors with divergent bin/ setups; symlinks created by an installer script.","solutions":["Remove the symlink (`git rm bin/<task>` for tracked, plain `rm` otherwise) and rerun `mise generate task-stubs`","If the link is load-bearing, rename the task or change --dir so they no longer collide","Adopt the committed-stub workflow the command exists for: generated stubs plus `mise generate bootstrap` replace symlink farms"],"exampleFix":"# before\n$ ls -l bin/build   # bin/build -> ../tools/build\n$ mise generate task-stubs\n# error: bin/build is a symbolic link\n\n# after\n$ git rm bin/build\n$ mise generate task-stubs","handlingStrategy":"type-guard","validationCode":"#!/bin/bash\n# refuse to generate over symlinks\nfind bin -type l -print -quit | grep -q . && { echo 'symlink under bin/' >&2; exit 1; }\nmise generate task-stubs","typeGuard":"is_writable_path() {\n  # 0 when path is absent or a real file/dir (not a symlink)\n  [ ! -L \"$1\" ] && { [ ! -e \"$1\" ] || [ -f \"$1\" ] || [ -d \"$1\" ]; }\n}","tryCatchPattern":null,"preventionTips":["Retire symlink-farm bin/ layouts before adopting task-stubs; commit generated stubs instead","Add a CI check (`find bin -type l`) so symlinks cannot sneak back in"],"tags":["mise","task-stubs","symlink","generate"],"backgroundTag":"symlink-conflict","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}