{"record":{"id":"7d7500178a2137dc","repo":"jdx/mise","slug":"pnpm-lockfile-dependency-name-has-no-resolvabl","errorCode":null,"errorMessage":"pnpm lockfile dependency {name:?} has no resolvable version","messagePattern":"pnpm lockfile dependency (.+?) has no resolvable version","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/task/workspace/node.rs","lineNumber":397,"sourceCode":"    }\n    Ok(reachable)\n}\n\nfn dependency_package_keys(node: &Value, available: &BTreeSet<String>) -> Result<Vec<String>> {\n    let mut packages = Vec::new();\n    for field in [\"dependencies\", \"devDependencies\", \"optionalDependencies\"] {\n        let Some(dependencies) = node.get(field).and_then(Value::as_mapping) else {\n            continue;\n        };\n        for (name, value) in dependencies {\n            let Some(name) = name.as_str() else {\n                continue;\n            };\n            let version = value\n                .as_str()\n                .or_else(|| value.get(\"version\").and_then(Value::as_str));\n            let Some(version) = version else {\n                eyre::bail!(\"pnpm lockfile dependency {name:?} has no resolvable version\");\n            };\n            packages.extend(resolve_package_keys(name, version, available)?);\n        }\n    }\n    Ok(packages)\n}\n\nfn resolve_package_keys(\n    name: &str,\n    version: &str,\n    available: &BTreeSet<String>,\n) -> Result<Vec<String>> {\n    if [\"link:\", \"workspace:\", \"file:\"]\n        .iter()\n        .any(|prefix| version.starts_with(prefix))\n    {\n        return Ok(Vec::new());\n    }","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/task/workspace/node.rs#L379-L415","documentation":"While walking a pnpm lockfile to compute reachable packages for workspace tasks, mise resolves each dependency entry to a version string. pnpm v9+ lockfiles can store importers/dependency entries where neither a direct string version nor a nested \"version\" field exists (e.g. link:/workspace-style or peer-only entries). Mise bails because it cannot map the dependency to a package snapshot.","triggerScenarios":"dependency_package_keys encounters a dependency in an importer block whose value is neither a version string nor an object with a version key — e.g. file:/ tarball deps, link: workspace deps, or a corrupted lockfile entry.","commonSituations":"pnpm lockfileVersion 9 with workspace link: dependencies; dependencies pointing at local tarballs (file:./pkg.tgz); git or patch-protocol deps lacking a resolved version field; hand-edited lockfiles.","solutions":["Run `pnpm install` to regenerate a complete, valid lockfile with resolved versions.","Replace file:/tarball or link: deps with regular registry versions where feasible.","Upgrade pnpm so workspace links are recorded with resolvable snapshots.","Inspect the offending dependency name in the error and fix or remove that entry."],"exampleFix":"// pnpm-lock.yaml (before)\ndeps:\n  my-pkg:\n    specifier: ^1.0.0\n// after (regenerated by pnpm install)\ndeps:\n  my-pkg:\n    specifier: ^1.0.0\n    version: 1.2.3","handlingStrategy":"validation","validationCode":"// before relying on mise workspace tasks:\n// ensure lockfile deps are resolvable\nconst deps = lock.importers.flatMap(i => ({...i.dependencies, ...i.devDependencies}));\nfor (const [name, v] of Object.entries(deps)) {\n  const version = typeof v === 'string' ? v : v?.version;\n  if (!version) console.warn(`dep ${name} has no resolvable version`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  mise('run', 'task');\n} catch (e) {\n  if (/has no resolvable version/.test(e.message)) {\n    execSync('pnpm install', { stdio: 'inherit' });\n  } else throw e;\n}","preventionTips":["Run `pnpm install` after editing package.json so the lockfile stays consistent.","Avoid link:/file:/tarball deps in packages mise analyzes for workspace tasks.","Never hand-edit pnpm-lock.yaml."],"tags":["pnpm","lockfile","node","workspace"],"backgroundTag":"record-not-found","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"}