{"record":{"id":"5db845cf27f3361e","repo":"CherryHQ/cherry-studio","slug":"missing-prebuilt-packages-for-platform-arch","errorCode":null,"errorMessage":"Missing prebuilt packages for ${platform}-${arch}: ${missingPackages.join(', ')}\nRun `rm -rf node_modules && pnpm install` — pnpm only reads supportedArchitectures on a fresh install, so plain `pnpm install` (even --force) will not fix it.","messagePattern":"Missing prebuilt packages for (.+?)-(.+?): (.+?)\nRun `rm -rf node_modules && pnpm install` — pnpm only reads supportedArchitectures on a fresh install, so plain `pnpm install` \\(even --force\\) will not fix it\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"scripts/before-pack.js","lineNumber":100,"sourceCode":"// Most native packages encode Electron's platform key (win32) in their name, but some\n// (e.g. sqlite-vec) use the npm `windows` convention. Match either so a win32 build keeps\n// sqlite-vec-windows-x64 instead of wrongly excluding it.\nconst keepPackages = (platform, arch) => {\n  const platformTokens = platform === 'win32' ? ['win32', 'windows'] : [platform]\n  return packages.filter((p) => p.includes(arch) && platformTokens.some((t) => p.includes(t)))\n}\n\n// Cross-arch prebuilt packages come from supportedArchitectures in pnpm-workspace.yaml —\n// pnpm ignores that setting once node_modules exists, so it can't be flipped per pack pass.\n// Anything kept for this arch but never installed is a native module the app would fail to\n// load at runtime, so stop here instead of shipping it. musl builds are excluded: pnpm\n// installs them only on a musl host, and releases are built on glibc.\nconst assertPrebuiltPackages = (platform, arch) => {\n  const missingPackages = keepPackages(platform, arch)\n    .filter((p) => !p.includes('musl'))\n    .filter((p) => !fs.existsSync(path.join(__dirname, '..', 'node_modules', p)))\n  if (missingPackages.length > 0) {\n    throw new Error(\n      `Missing prebuilt packages for ${platform}-${arch}: ${missingPackages.join(', ')}\\n` +\n        `Run \\`rm -rf node_modules && pnpm install\\` — pnpm only reads supportedArchitectures ` +\n        `on a fresh install, so plain \\`pnpm install\\` (even --force) will not fix it.`\n    )\n  }\n}\nexports.assertPrebuiltPackages = assertPrebuiltPackages\n\nexports.default = async function (context) {\n  const arch = context.arch === Arch.arm64 ? 'arm64' : 'x64'\n  const platformName = context.packager.platform.name\n  const platform = platformToArch[platformName]\n\n  assertPrebuiltPackages(platform, arch)\n\n  if (platform === 'linux') {\n    const linuxArch = context.arch === Arch.arm64 ? 'arm64' : context.arch === Arch.x64 ? 'x64' : null\n    if (!linuxArch) throw new Error(`Unsupported Linux packaging architecture: ${context.arch}`)","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/scripts/before-pack.js#L82-L118","documentation":"Thrown by scripts/before-pack.js during electron-builder packaging when one or more native prebuilt packages required for the target platform/arch are not present in node_modules. Cross-arch prebuilts are pulled in via supportedArchitectures in pnpm-workspace.yaml, but pnpm only honors that setting on a fresh install — once node_modules exists it ignores changes. Shipping without them would crash at runtime on native module load, so the build stops here.","triggerScenarios":"Building for an arch you have not freshly installed for (e.g. node_modules installed on an x64 host, then building a win32-arm64 or linux-arm64 target). Also when supportedArchitectures in pnpm-workspace.yaml was edited but pnpm install was run incrementally instead of cleanly, or when a new native package was added to the packages list but not to supportedArchitectures.","commonSituations":"CI cached node_modules from a prior arch build; a developer toggling arch targets without wiping node_modules; adding a new native dependency (e.g. a new @img/sharp-* variant) and forgetting to declare it in supportedArchitectures; switching between glibc and musl targets.","solutions":["Wipe and reinstall so pnpm re-reads supportedArchitectures: rm -rf node_modules && pnpm install. (The error message calls this out — plain pnpm install or pnpm install --force will NOT fix it.)","Confirm the target platform/arch combinations are listed in supportedArchitectures inside pnpm-workspace.yaml.","If you added a new native package, add its platform/arch variants to both the packages array in before-pack.js and supportedArchitectures in pnpm-workspace.yaml.","In CI, do not share/restamp a single node_modules cache across arch matrix entries — key the cache by arch."],"exampleFix":"# before (fails)\npnpm install --force # pnpm ignores supportedArchitectures on existing node_modules\n\n# after\nrm -rf node_modules && pnpm install","handlingStrategy":"validation","validationCode":"// Pre-build check: ensure every required native package is installed for this arch\nconst fs = require('fs')\nconst path = require('path')\nconst { keepPackages } = require('./scripts/before-pack')\n// keepPackages is not exported; replicate the filter or export it for reuse\nconst missing = require('./scripts/before-pack').assertPrebuiltPackages\n// Simpler: run the assert before electron-builder in CI\n// node -e \"require('./scripts/before-pack').assertPrebuiltPackages('linux','arm64')\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always run rm -rf node_modules && pnpm install when switching arch targets — pnpm ignores supportedArchitectures on existing node_modules.","Key CI node_modules caches by target arch, not shared across arches.","When adding a native dependency, add it to both before-pack.js packages list and pnpm-workspace.yaml supportedArchitectures."],"tags":["build","packaging","native-modules","pnpm","electron-builder"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}