paperclipai/paperclip · error · Error
Migrator shared dependency mismatch.
Error message
Migrator shared dependency mismatch.
What it means
assertLockfile requires the @paperclipai/db lockfile entry to declare an exact-version dependency on @paperclipai/shared, equal to manifest.packageVersion. This keeps the two internal packages co-pinned so a migrator install can never mix package versions. The error fires when that nested dependency pin is missing or differs from the manifest version.
Solutions
- Ensure @paperclipai/db's package.json depends on @paperclipai/shared at the same exact version, then re-run the `build` command to regenerate the lockfile
- Bump both packages together so their versions match the manifest packageVersion
- Verify the db package.json included in the tgz (checked via tarManifest) declares the pinned shared dependency
Example fix
// before (db package.json)
"dependencies": { "@paperclipai/shared": "^0.4.1" }
// after
"dependencies": { "@paperclipai/shared": "0.4.2" } Defensive patterns
Strategy: validation
Validate before calling
const dbEntry = lock.packages?.["node_modules/@paperclipai/db"];
const pinned = dbEntry?.dependencies?.["@paperclipai/shared"];
if (pinned !== manifest.packageVersion) throw new Error(`@paperclipai/shared pin is ${pinned}, expected ${manifest.packageVersion}`); Type guard
const sharedPinOk = (lock, manifest) => lock?.packages?.["node_modules/@paperclipai/db"]?.dependencies?.["@paperclipai/shared"] === manifest.packageVersion;
Try / catch
try {
assertLockfile(lock, manifest);
} catch (err) {
if (err.message === "Migrator shared dependency mismatch.") throw new Error("Rebuild the bundle: db must depend on shared at the exact manifest version");
throw err;
} Prevention
- Keep @paperclipai/db's dependency on @paperclipai/shared an exact version, never a range
- Bump both packages in lockstep so their versions always match
- Rebuild the lockfile after any package.json dependency change
- Run `validate` on the bundle before publishing
When it happens
Trigger: assertLockfile(lock, manifest) sees lock.packages["node_modules/@paperclipai/db"].dependencies["@paperclipai/shared"] !== manifest.packageVersion (missing, a range like ^0.4.2, or an older exact version).
Common situations: The db package.json's dependency on @paperclipai/shared was a semver range or stale version when npm generated the lockfile; someone hand-edited the lockfile; packages were bumped independently without a rebuild.
Related errors
- Invalid migrator lockfile entry.
- Migrator dependency has no strong integrity pin.
- Migrator dependency must resolve to npm.
- Migrator lockfile package pin mismatch.
- Unexpected internal migrator dependency.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/3b56483a2240081d.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/cloud-migrator-artifacts.mjs:48
}
}
export function assertManifest(manifest, sha) {
if (manifest?.version !== 1 || manifest.sourceSha !== sha || manifest.packageVersion !== versionFor(sha)) throw new Error("Artifact source identity mismatch.");
for (const name of names) assertDescriptor(manifest.packages?.[name], "tgz");
assertDescriptor(manifest.lockfile, "json");
}
export function assertLockfile(lock, manifest) {
const version = manifest.packageVersion;
if (lock?.lockfileVersion !== 3 || !lock.packages || Array.isArray(lock.packages) ||
JSON.stringify(lock.packages[""]?.dependencies) !== JSON.stringify({ "@paperclipai/db": version })) throw new Error("Invalid migrator lockfile root.");
for (const name of names) {
const pin = lock.packages[`node_modules/@paperclipai/${name}`];
const expected = manifest.packages[name];
if (pin?.version !== version || pin.integrity !== expected.integrity || pin.resolved !== expected.url || pin.link || pin.inBundle) throw new Error("Migrator lockfile package pin mismatch.");
}
if (lock.packages["node_modules/@paperclipai/db"].dependencies?.["@paperclipai/shared"] !== version) throw new Error("Migrator shared dependency mismatch.");
for (const [key, entry] of Object.entries(lock.packages)) {
if (key === "") continue;
if (!entry || typeof entry !== "object" || entry.link) throw new Error("Invalid migrator lockfile entry.");
if (/(?:^|\/)node_modules\/@paperclipai\/[^/]+$/.test(key) && !names.some((name) => key === `node_modules/@paperclipai/${name}`)) throw new Error("Unexpected internal migrator dependency.");
if (entry.inBundle === true) {
if (!key.startsWith("node_modules/@paperclipai/db/node_modules/")) throw new Error("Unexpected bundled dependency.");
continue;
}
if (!/^sha512-[A-Za-z0-9+/]{86}==$/.test(entry.integrity ?? "")) throw new Error("Migrator dependency has no strong integrity pin.");
if (names.some((name) => key === `node_modules/@paperclipai/${name}`)) continue;
const url = new URL(entry.resolved);
if (url.origin !== "https://registry.npmjs.org" || url.username || url.password || url.search || url.hash) throw new Error("Migrator dependency must resolve to npm.");
}
}
export function buildBundle(directory, sha, { exec = execFileSync } = {}) {
versionFor(sha);
directory = path.resolve(directory);View on GitHub (pinned to 3f1d897a7c)