{"record":{"id":"f61b69bfdf9558b2","repo":"thedotmack/claude-mem","slug":"post-install-check-failed-unresolvable-modules","errorCode":null,"errorMessage":"Post-install check failed: unresolvable modules: ${unresolvable.join(', ')}","messagePattern":"Post-install check failed: unresolvable modules: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/npx-cli/install/setup-runtime.ts","lineNumber":296,"sourceCode":"  }\n\n  // zod ships its public API behind subpath exports the worker bundle requires.\n  // The package dir existing does NOT imply these subpaths resolve (#2730).\n  if (dependencies.includes('zod')) {\n    for (const subpath of ZOD_REQUIRED_SUBPATHS) {\n      try {\n        requireFromTarget.resolve(subpath, { paths: resolvePaths });\n      } catch {\n        // [ANTI-PATTERN IGNORED]: subpath resolve failure is the condition being\n        // probed; it is collected in `unresolvable` and surfaced as a loud\n        // install failure below.\n        unresolvable.push(subpath);\n      }\n    }\n  }\n\n  if (unresolvable.length > 0) {\n    throw new Error(\n      `Post-install check failed: unresolvable modules: ${unresolvable.join(', ')}`,\n    );\n  }\n}\n\n/** Build an ephemeral summary so callers (e.g. repair) may omit it. */\nfunction summaryOrEphemeral(summary?: InstallSummary): InstallSummary {\n  return summary ?? { warnings: [], failedIDEs: [] };\n}\n\nexport async function ensureBun(summary?: InstallSummary): Promise<{ bunPath: string; version: string }> {\n  const sum = summaryOrEphemeral(summary);\n  if (!isBunInstalled()) {\n    // installBun throws a platform-specific Error on failure; route it through\n    // the central decision point so it becomes a loud ABORT (bun is mandatory\n    // for hooks — there is no opt-out).\n    try {\n      installBun();","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/npx-cli/install/setup-runtime.ts#L278-L314","documentation":"Thrown by verifyCriticalModules() when one or more declared dependencies cannot be resolved from node_modules, or when the required zod subpath exports ('zod/v3','zod/v4','zod/v4-mini') fail to resolve. The check exists because a stale/partial install can leave package directories present while their importable entry points or subpath exports are broken — which would later surface as a runtime 'Cannot find module'. It fails loud at install time instead.","triggerScenarios":"An interrupted/partial `bun install` left node_modules incomplete. A package's exports map changed (or a pinned version lacks the subpath) so zod/v3 etc. no longer resolve. A corrupted node_modules where the dir exists but the entry file is missing. A dependency that is bin-only AND whose package.json itself is unresolvable (both resolves fail).","commonSituations":"Switching node_modules between package managers (npm/pnpm/bun) without a clean reinstall. A lockfile drift where installed versions don't match. A node_modules restored from a broken cache. Renamed/moved deps after a branch switch without reinstalling.","solutions":["Delete node_modules and the lockfile cache, then run a clean `bun install` (or the project's install command) and retry.","If a zod subpath is listed, confirm the installed zod version ships that subpath export; pin/upgrade zod if not.","If a bin-only dependency is flagged, ensure both its bare name and its package.json fail to resolve — if only the bare name fails, that path may need fixing in the resolver, but the fallback to <dep>/package.json already handles true bin-only packages.","Verify the target dir passed to verifyCriticalModules is the one whose node_modules you just installed into."],"exampleFix":"# before — partial node_modules\n# (verifyCriticalModules throws on missing zod/v3)\n# after — clean reinstall\nrm -rf node_modules && bun install","handlingStrategy":"validation","validationCode":"import { createRequire } from 'module';\nimport { existsSync } from 'fs';\nconst req = createRequire(join(targetDir, 'node_modules', 'noop.js'));\nfor (const sub of ['zod/v3','zod/v4','zod/v4-mini']) {\n  try { req.resolve(sub, { paths: [join(targetDir,'node_modules')] }); }\n  catch { throw new Error(`Run a clean install: cannot resolve ${sub}`); }\n}","typeGuard":"function allResolve(targetDir: string, deps: string[]): boolean {\n  const req = createRequire(join(targetDir, 'node_modules', 'noop.js'));\n  return deps.every(d => { try { req.resolve(d, { paths: [join(targetDir,'node_modules')] }); return true; } catch { return false; } });\n}","tryCatchPattern":"try {\n  verifyCriticalModules(targetDir);\n} catch (e) {\n  if (e instanceof Error && /unresolvable modules/.test(e.message)) {\n    // wipe node_modules and run a clean install, then retry\n  }\n  throw e;\n}","preventionTips":["Always reinstall cleanly (rm -rf node_modules) when switching package managers or branches.","Pin zod to a version that ships the v3/v4/v4-mini subpath exports.","Run verifyCriticalModules in CI immediately after install to catch partial node_modules early."],"tags":["install","dependencies","modules","node-modules","zod"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}