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

  1. 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
  2. Bump both packages together so their versions match the manifest packageVersion
  3. 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

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


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)