{"record":{"id":"c1d08741822e910a","repo":"jdx/mise","slug":"cannot-store-dependency-sidecar-for-invalid-version-version","errorCode":null,"errorMessage":"cannot store dependency sidecar for invalid version {version}","messagePattern":"cannot store dependency sidecar for invalid version (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lockfile/graph.rs","lineNumber":344,"sourceCode":"            root: absolute(&sidecar_root(lockfile)),\n            ..Default::default()\n        }\n    }\n    pub(super) fn reserve<T: NativeGraph>(&mut self, graph: &GraphRef<T>) {\n        if let Some(dir) = graph.dir().filter(|dir| dir.starts_with(&self.root)) {\n            self.referenced.insert(dir.to_path_buf());\n        }\n    }\n    pub(super) fn prepare<T: NativeGraph>(\n        &mut self,\n        graph: &GraphRef<T>,\n        short: &str,\n        version: &str,\n        backend: Option<&str>,\n        options: &std::collections::BTreeMap<String, String>,\n    ) -> Result<GraphRef<T>> {\n        if !crate::file::is_plain_file_name(version) {\n            bail!(\"cannot store dependency sidecar for invalid version {version}\");\n        }\n        let dir = if let Some(dir) = graph.dir().filter(|dir| dir.starts_with(&self.root)) {\n            dir.to_path_buf()\n        } else {\n            let parent = self.root.join(crate::backend::tool_directory_name(short));\n            let plain = parent.join(version);\n            if !options.is_empty() || self.referenced.contains(&plain) {\n                parent.join(format!(\"{version}~{}\", variant_suffix(backend, options)))\n            } else {\n                plain\n            }\n        };\n        self.referenced.insert(dir.clone());\n        if matches!(graph, GraphRef::Sidecar { dir: source, .. } if *source == dir && source.is_dir())\n        {\n            return Ok(graph.clone());\n        }\n        let body = match graph.load() {","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/lockfile/graph.rs#L326-L362","documentation":"`ToolVersionSource::prepare` stores a dependency sidecar under the tool's version directory. Before doing so it requires the version string to be a plain file name (`is_plain_file_name`) — no path separators or special characters — because the version is used to build the on-disk directory path. Otherwise it bails to avoid writing to unintended locations.","triggerScenarios":"Calling `prepare` (during lockfile dependency handling) with a tool version like `ref:main`, `path:../foo`, `latest`, `lts/hydrogen`, or a version containing `/` or other non-plain-file characters; also when the graph dir is outside the managed root so a fresh version-based dir must be derived.","commonSituations":"Locking tools installed from git refs, paths, or channel aliases rather than concrete released versions; custom/non-semver version strings from plugins; tools installed via `mise use node@lts/iron`.","solutions":["Pin the tool to a concrete, plain version (e.g. `node@22.1.0`) before lockfile generation","Resolve channel/ref aliases (latest, lts/*, ref:*) to concrete versions first","Update the plugin/backend to emit plain version names for installed versions","If intentional, skip dependency sidecar generation for that tool"],"exampleFix":"# before\nnode = \"lts/iron\"   # cannot store sidecar\n# after\nnode = \"22.11.0\"","handlingStrategy":"validation","validationCode":"fn is_plain_version(v: &str) -> bool {\n    !v.is_empty()\n        && !v.contains('/')\n        && !v.contains('\\\\')\n        && !v.contains(':')\n        && v != \".\" && v != \"..\"\n}","typeGuard":"fn plain_version(v: &str) -> Option<&str> {\n    (!v.is_empty()\n        && !v.contains('/')\n        && !v.contains('\\\\')\n        && !v.contains(':')).then_some(v)\n}","tryCatchPattern":null,"preventionTips":["Pin tools to concrete released versions before generating lockfiles","Resolve ref:/path:/lts/latest aliases to concrete versions first","Avoid locking dependency sidecars for tools installed from git refs or paths","Validate plugin-reported version strings before storing them"],"tags":["lockfile","sidecar","versioning"],"backgroundTag":"invalid-identifier-format","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"}