{"record":{"id":"ef4586ecf23cb566","repo":"jdx/mise","slug":"must-provide-a-version-for","errorCode":null,"errorMessage":"must provide a version for {}","messagePattern":"must provide a version for (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/link.rs","lineNumber":42,"sourceCode":"    /// The local path to the tool version\n    /// e.g.: ~/.nvm/versions/node/v20.0.0\n    #[clap(value_hint = ValueHint::DirPath, verbatim_doc_comment)]\n    path: PathBuf,\n\n    /// Overwrite an existing tool version if it exists\n    #[clap(long, short = 'f')]\n    force: bool,\n}\n\nimpl Link {\n    pub async fn run(self) -> Result<()> {\n        let tvr = match self.tool.tvr.as_ref() {\n            Some(tvr @ (ToolRequest::Version { .. } | ToolRequest::Ref { .. })) => tvr,\n            Some(tvr) => bail!(\n                \"mise link only supports concrete versions and refs, not {}\",\n                tvr.version()\n            ),\n            None => bail!(\"must provide a version for {}\", self.tool.style()),\n        };\n        let config = Config::get().await?;\n        let version_pathname = match tvr {\n            ToolRequest::Version { version, .. } => {\n                let backend = tvr.backend()?;\n                let resolved_alias = config.resolve_alias(&backend, version).await?;\n                if version == \"latest\"\n                    || resolved_alias != *version\n                    || backend.is_rolling_channel(version)\n                {\n                    bail!(\n                        \"mise link only supports concrete versions and refs, not {}\",\n                        tvr.version()\n                    );\n                }\n                ToolVersion::new(tvr.clone(), version.clone()).tv_pathname()\n            }\n            ToolRequest::Ref { .. } => ToolVersion::new(tvr.clone(), tvr.version()).tv_pathname(),","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/cli/link.rs#L24-L60","documentation":"`mise link` requires the tool argument to carry a version (TOOL@VERSION). When the arg parses to a tool with no version request at all (just `node`), there is nothing to name the linked directory after, so it bails with 'must provide a version'. Unlike the alias cases, this one fires before any config lookup.","triggerScenarios":"`mise link node /opt/node` (forgot @version); a wrapper script that concatenates tool and version with a missing '@'; env var for the version being empty so the arg degrades to the bare tool name.","commonSituations":"First-time use of mise link assuming it picks the installed/latest version; shell variable mistakes like `mise link node@$V` with V unset (which usually fails parsing earlier, but tool-only args always land here).","solutions":["Add an explicit version: `mise link node@22.17.1 /opt/node-22`","Resolve dynamically: `mise link node@$(mise latest node) /opt/node-22`","Check wrapper scripts interpolate the version correctly before invoking mise link"],"exampleFix":"# before\nmise link node /opt/node-v22\n# after\nmise link node@22.17.1 /opt/node-v22","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n[[ \"$arg\" == *@* ]] || { echo \"mise link requires TOOL@VERSION\" >&2; exit 2; }\nmise link \"$arg\" \"$path\"","typeGuard":null,"tryCatchPattern":"mise link \"$tool\" \"$path\" 2>err.log || { grep -q 'must provide a version' err.log && mise link \"$tool@$(mise latest \"$tool\")\" \"$path\"; }","preventionTips":["Always type TOOL@VERSION for link; there is no default-version pickup","Interpolate resolved versions from `mise latest` in automation"],"tags":["cli","link","missing-argument","mise"],"backgroundTag":"missing-required-argument","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}