{"record":{"id":"51387d5ec480b1ff","repo":"paperclipai/paperclip","slug":"unexpected-bundled-dependency","errorCode":null,"errorMessage":"Unexpected bundled dependency.","messagePattern":"Unexpected bundled dependency\\.","errorType":"console","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/cloud-migrator-artifacts.mjs","lineNumber":54,"sourceCode":"  assertDescriptor(manifest.lockfile, \"json\");\n}\n\nexport function assertLockfile(lock, manifest) {\n  const version = manifest.packageVersion;\n  if (lock?.lockfileVersion !== 3 || !lock.packages || Array.isArray(lock.packages) ||\n      JSON.stringify(lock.packages[\"\"]?.dependencies) !== JSON.stringify({ \"@paperclipai/db\": version })) throw new Error(\"Invalid migrator lockfile root.\");\n  for (const name of names) {\n    const pin = lock.packages[`node_modules/@paperclipai/${name}`];\n    const expected = manifest.packages[name];\n    if (pin?.version !== version || pin.integrity !== expected.integrity || pin.resolved !== expected.url || pin.link || pin.inBundle) throw new Error(\"Migrator lockfile package pin mismatch.\");\n  }\n  if (lock.packages[\"node_modules/@paperclipai/db\"].dependencies?.[\"@paperclipai/shared\"] !== version) throw new Error(\"Migrator shared dependency mismatch.\");\n  for (const [key, entry] of Object.entries(lock.packages)) {\n    if (key === \"\") continue;\n    if (!entry || typeof entry !== \"object\" || entry.link) throw new Error(\"Invalid migrator lockfile entry.\");\n    if (/(?:^|\\/)node_modules\\/@paperclipai\\/[^/]+$/.test(key) && !names.some((name) => key === `node_modules/@paperclipai/${name}`)) throw new Error(\"Unexpected internal migrator dependency.\");\n    if (entry.inBundle === true) {\n      if (!key.startsWith(\"node_modules/@paperclipai/db/node_modules/\")) throw new Error(\"Unexpected bundled dependency.\");\n      continue;\n    }\n    if (!/^sha512-[A-Za-z0-9+/]{86}==$/.test(entry.integrity ?? \"\")) throw new Error(\"Migrator dependency has no strong integrity pin.\");\n    if (names.some((name) => key === `node_modules/@paperclipai/${name}`)) continue;\n    const url = new URL(entry.resolved);\n    if (url.origin !== \"https://registry.npmjs.org\" || url.username || url.password || url.search || url.hash) throw new Error(\"Migrator dependency must resolve to npm.\");\n  }\n}\n\nexport function buildBundle(directory, sha, { exec = execFileSync } = {}) {\n  versionFor(sha);\n  directory = path.resolve(directory);\n  const packages = {};\n  for (const name of names) {\n    const bytes = readFileSync(path.join(directory, `${name}.tgz`));\n    assertMetadata(tarManifest(bytes), `@paperclipai/${name}`, sha);\n    packages[name] = descriptor(bytes, \"tgz\");\n  }","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/scripts/cloud-migrator-artifacts.mjs#L36-L72","documentation":"Bundled (inBundle) dependencies are only allowed under node_modules/@paperclipai/db/node_modules/. This error fires when the lockfile marks some other package as bundled — a package whose bytes ship inside another tarball rather than resolving from a registry — outside the one permitted location. Bundled deps elsewhere cannot be integrity-pinned consistently.","triggerScenarios":"assertLockfile iterates lock.packages and finds an entry with inBundle === true whose key does not start with node_modules/@paperclipai/db/node_modules/ (e.g. shared bundling a dep, or a root-level bundled package).","commonSituations":"A package.json gained bundledDependencies/bundleDependencies listing a package; npm packed a dep into the shared tarball; lockfile generated from a different packing configuration than the build expects.","solutions":["Remove the bundledDependencies declaration (or move it so only db may bundle), then rebuild the lockfile","Re-run `node scripts/cloud-migrator-artifacts.mjs build <dir> <sha>` after changing the bundling config","Inspect the entry's key to find which package introduced the bundle and fix at the source package.json"],"exampleFix":"// before (shared package.json)\n\"bundleDependencies\": [\"some-dep\"]\n// after (removed; dep resolves from registry with integrity pin)\n\"dependencies\": { \"some-dep\": \"^1.0.0\" }","handlingStrategy":"validation","validationCode":"for (const [key, entry] of Object.entries(lock.packages ?? {})) {\n  if (entry?.inBundle === true && !key.startsWith(\"node_modules/@paperclipai/db/node_modules/\"))\n    throw new Error(`unexpected bundled dep: ${key}`);\n}","typeGuard":"const bundlesOnlyUnderDb = (lock) =>\n  Object.entries(lock?.packages ?? {}).every(([key, entry]) =>\n    entry?.inBundle !== true || key.startsWith(\"node_modules/@paperclipai/db/node_modules/\"));","tryCatchPattern":"try {\n  assertLockfile(lock, manifest);\n} catch (err) {\n  if (err.message === \"Unexpected bundled dependency.\") throw new Error(\"Remove bundledDependencies outside @paperclipai/db and rebuild\");\n  throw err;\n}","preventionTips":["Do not declare bundledDependencies in @paperclipai/shared or the install root","Rebuild the lockfile after changing any packing/bundling configuration","Inspect entry.inBundle flags in the lockfile before publishing","Keep dependency resolution registry-based (bundling bypasses integrity pins)"],"tags":["lockfile","npm","bundling","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}