{"record":{"id":"ac9dd3050f6bed07","repo":"jdx/mise","slug":"npm-dependency-graph-does-not-match-root-version-run-mise","errorCode":null,"errorMessage":"npm:{} dependency graph does not match root version {}; run `mise lock`","messagePattern":"npm:(.+?) dependency graph does not match root version (.+?); run `mise lock`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/backend/npm.rs","lineNumber":1546,"sourceCode":"        )?;\n        Ok(())\n    }\n\n    pub(crate) fn validate_aube_lock(\n        &self,\n        tv: &ToolVersion,\n        lock: &crate::lockfile::AubeLock,\n    ) -> Result<()> {\n        let requirement = lock\n            .graph\n            .get(\"importers\")\n            .and_then(|v| v.get(\".\"))\n            .and_then(|v| v.get(\"dependencies\"))\n            .and_then(|v| v.get(self.tool_name()))\n            .and_then(|v| v.get(\"specifier\"))\n            .and_then(toml::Value::as_str);\n        if requirement != Some(tv.version.as_str()) {\n            eyre::bail!(\n                \"npm:{} dependency graph does not match root version {}; run `mise lock`\",\n                self.tool_name(),\n                tv.version\n            );\n        }\n        Ok(())\n    }\n\n    pub(crate) async fn resolve_aube_lock(\n        &self,\n        tv: &ToolVersion,\n    ) -> Result<crate::lockfile::GraphRef<crate::lockfile::AubeLock>> {\n        crate::backend::aube_host::init();\n        let temp = tempfile::tempdir()?;\n        let request_options = tv.request.options();\n        let options = NpmOptions::new(&request_options);\n        let allow_builds = options.allow_builds()?;\n        self.write_aube_embed_project(temp.path(), tv.before_date, &options, &allow_builds, false)?;","sourceCodeStart":1528,"sourceCodeEnd":1564,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/backend/npm.rs#L1528-L1564","documentation":"validate_aube_lock checks that the lockfile's embedded aube dependency graph records the root package's dependency specifier equal to the requested tool version. If the graph's root specifier for the tool differs from tv.version, the lockfile is stale relative to the requested version, and mise bails directing the user to re-lock.","triggerScenarios":"Requesting npm:<tool>@X while mise.lock's aube graph maps \".\" -> dependencies -> <tool> -> specifier to a different version Y; mise.toml bumps the tool version without running `mise lock`; lockfile committed for a different version than the config requests.","commonSituations":"A developer edits the tool version in mise.toml but forgets to run `mise lock`; pulling a config change from git without the matching lockfile update; rebasing that merged version bump but not lock regeneration.","solutions":["Run `mise lock` so the dependency graph matches the requested root version.","If the version in mise.toml is wrong, revert it to the locked version instead.","Commit mise.toml and mise.lock changes together to keep them in sync."],"exampleFix":"// before (mise.toml bumped without re-lock)\n[tools]\n\"npm:eslint\" = \"9.10.0\"   # lockfile still has specifier = 9.9.0\n\n// after\n$ mise lock   # regenerates graph for 9.10.0","handlingStrategy":"validation","validationCode":"# verify root specifier in lockfile matches mise.toml version\n# mise.toml: \"npm:eslint\" = \"9.10.0\"\ngrep -A3 '\\[.*dependencies.*eslint\\]' mise.lock  # specifier should equal 9.10.0","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always run `mise lock` immediately after bumping an npm tool version in mise.toml","Commit mise.toml and mise.lock together","Use `mise upgrade <tool>` instead of hand-editing versions so the lock stays in sync"],"tags":["npm","lockfile","aube","version-mismatch"],"backgroundTag":"checksum-mismatch","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"}