{"record":{"id":"a1b2dd8fe289ba7d","repo":"jdx/mise","slug":"lockfile-contains-multiple-resolutions-for-short","errorCode":null,"errorMessage":"lockfile contains multiple resolutions for {short}@{specifier} with the same options","messagePattern":"lockfile contains multiple resolutions for (.+?)@(.+?) with the same options","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lockfile.rs","lineNumber":3664,"sourceCode":"        }\n    };\n\n    if let Some(tools) = lockfile.tools.get(short) {\n        if lockfile.uses_request_bindings() {\n            let matching = tools\n                .iter()\n                .filter(|tool| {\n                    tool.specifiers.contains(specifier) && &tool.options == request_options\n                })\n                .collect_vec();\n            match matching.as_slice() {\n                [] => {}\n                [found] => {\n                    trace!(\"[{short}@{specifier}] found {} in lockfile\", found.version);\n                    return Ok(Some((*found).clone()));\n                }\n                _ => {\n                    bail!(\n                        \"lockfile contains multiple resolutions for {short}@{specifier} with the same options\"\n                    )\n                }\n            }\n\n            if legacy_options_fallback && !request_options.is_empty() {\n                let legacy = tools\n                    .iter()\n                    .filter(|tool| tool.specifiers.contains(specifier) && tool.options.is_empty())\n                    .collect_vec();\n                match legacy.as_slice() {\n                    [] => {}\n                    [found] => {\n                        trace!(\n                            \"[{short}@{specifier}] found {} in lockfile without options, keeping the version pin and dropping its artifact data\",\n                            found.version\n                        );\n                        return Ok(Some(lockfile_tool_with_request_options(","sourceCodeStart":3646,"sourceCodeEnd":3682,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/lockfile.rs#L3646-L3682","documentation":"During lockfile resolution lookup, mise filters lockfile entries for short@specifier matching the request options. If more than one entry matches with identical options, the resolution is ambiguous and mise refuses to pick arbitrarily, bailing with this message.","triggerScenarios":"Looking up a resolution in mise.lock where the entries array contains two or more LockfileTool entries for the same short name + specifier with the same options hash. Produced by corrupted lockfiles, bad merges that duplicated entries, or concurrent writes.","commonSituations":"A git merge duplicated [[tools.x]] entries; a crash or race during `mise lock` left duplicate rows; hand-editing copied an entry without removing the old one.","solutions":["Remove the duplicate [[tools.<short>]] entries in mise.lock, keeping exactly one per (specifier, options) combination","Regenerate the lockfile: delete it and run `mise lock` / `mise install` to rebuild clean entries","Restore mise.lock from a known-good commit if the corruption came from a merge"],"exampleFix":"# before (mise.lock): two identical entries\n[[tools.node]]\nversion = \"20.0.0\"\n[[tools.node]]\nversion = \"20.0.0\"\n# after\n[[tools.node]]\nversion = \"20.0.0\"","handlingStrategy":"validation","validationCode":"// Detect duplicate (specifier, options) tool entries before resolution\nfn has_duplicates(entries: &[TomlToolEntry]) -> bool {\n    let mut seen = std::collections::HashSet::new();\n    entries.iter().any(|e| !seen.insert((e.specifier.clone(), e.options.clone())))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never merge mise.lock by hand — regenerate instead","Run `mise lock` atomically; avoid concurrent mise processes writing the same lockfile","Review lockfile diffs for duplicated entries before committing"],"tags":["lockfile","ambiguity","duplicates"],"backgroundTag":"internal-invariant-violation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}