{"record":{"id":"5b8935eb6d66c964","repo":"jdx/mise","slug":"invalid-lockfile-format-for-tool-short-expected","errorCode":null,"errorMessage":"invalid lockfile format for tool {short}: expected array ([[tools.{short}]])","messagePattern":"invalid lockfile format for tool (.+?): expected array \\(\\[\\[tools\\.(.+?)\\]\\]\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lockfile.rs","lineNumber":892,"sourceCode":"        let mut table: toml::Table = toml::from_str(&content)?;\n\n        let tools: toml::Table = table\n            .remove(\"tools\")\n            .unwrap_or(toml::Table::new().into())\n            .try_into()?;\n\n        let mut lockfile = Lockfile {\n            generated_header_url,\n            ..Default::default()\n        };\n\n        for (short, value) in tools {\n            let versions = match value {\n                toml::Value::Array(arr) => arr\n                    .into_iter()\n                    .map(LockfileTool::try_from)\n                    .collect::<Result<Vec<_>>>()?,\n                _ => bail!(\n                    \"invalid lockfile format for tool {short}: expected array ([[tools.{short}]])\"\n                ),\n            };\n            lockfile.tools.insert(short, versions);\n        }\n\n        // Parse conda-packages section: platform -> basename -> CondaPackageInfo\n        if let Some(conda_packages) = table.remove(\"conda-packages\") {\n            let platforms: toml::Table = conda_packages.try_into()?;\n            for (platform, packages) in platforms {\n                let packages_table: toml::Table = packages.try_into()?;\n                for (basename, info) in packages_table {\n                    let info: CondaPackageInfo = info.try_into()?;\n                    lockfile\n                        .conda_packages\n                        .entry(platform.clone())\n                        .or_default()\n                        .insert(basename, info);","sourceCodeStart":874,"sourceCodeEnd":910,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/lockfile.rs#L874-L910","documentation":"In mise.lock, each tools.<short> value must be an array of tables — one [[tools.<short>]] entry per locked version (src/lockfile.rs:883-894). A non-array value (inline table, bare string) bails, naming the tool.","triggerScenarios":"tools.node = \"22\" or tools.python = { version = \"3.12\" } in mise.lock — hand-edited files, output from a much older/experimental mise format, or structural drift between versions.","commonSituations":"Hand-editing mise.lock instead of using mise lock; lockfiles produced by pre-release formats; merge conflicts resolved incorrectly.","solutions":["Regenerate the lockfile: rm mise.lock && mise lock.","Upgrade mise so writer and reader agree on the [[tools.<name>]] shape.","Resolve lockfile merge conflicts by regenerating, not by hand-merging."],"exampleFix":"# before (mise.lock, wrong shape)\n[tools]\nnode = \"22.0.0\"\n\n# after — regenerate; correct shape is one [[tools.node]] table per version\n$ rm mise.lock && mise lock","handlingStrategy":"validation","validationCode":"# CI guard: tools.<short> must be an array (of tables)\npython3 -c \"\nimport tomllib\nfor name, v in tomllib.load(open('mise.lock', 'rb')).get('tools', {}).items():\n    if not isinstance(v, list):\n        raise SystemExit('tools.%s must be an array of tables' % name)\n\"","typeGuard":null,"tryCatchPattern":"On \"invalid lockfile format for tool …\", regenerate the lockfile rather than reshaping it by hand; if the shape came from another mise version, upgrade/downgrade to match before re-locking, then fail the job with that guidance if lockfiles are protected.","preventionTips":["Always create lockfiles via mise lock, never by writing TOML manually.","Resolve mise.lock merge conflicts by regenerating.","Pin one mise version repo-wide to keep the file shape stable."],"tags":["lockfile","parse","toml","structure"],"backgroundTag":"invalid-lockfile-format","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}