{"record":{"id":"504055fb9e6a5ab6","repo":"can1357/oh-my-pi","slug":"source-deps-tree-has-no-node-modules-depsdir","errorCode":null,"errorMessage":"source deps tree has no node_modules (${depsDir}); delete it and retry","messagePattern":"source deps tree has no node_modules \\((.+?)\\); delete it and retry","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/metaharness/src/runner.ts","lineNumber":1162,"sourceCode":"\t\t\t\t\t\t`linux/${arch === \"x64\" ? \"amd64\" : \"arm64\"}`,\n\t\t\t\t\t\t\"-e\",\n\t\t\t\t\t\t\"HOME=/tmp\",\n\t\t\t\t\t\t\"-v\",\n\t\t\t\t\t\t`${depsDir}:/deps`,\n\t\t\t\t\t\timage,\n\t\t\t\t\t\t\"sh\",\n\t\t\t\t\t\t\"-c\",\n\t\t\t\t\t\tscript,\n\t\t\t\t\t];\n\t\tconst r = spawnSync(runArgv[0], runArgv.slice(1), { stdio: [\"ignore\", \"inherit\", \"inherit\"] });\n\t\tif (r.status !== 0) {\n\t\t\tfs.rmSync(stampFile, { force: true });\n\t\t\tthrow new Error(`source deps install failed (${runArgv[0]} exit ${r.status})`);\n\t\t}\n\t\tfs.writeFileSync(stampFile, `${stamp}\\n`);\n\t}\n\tif (!fs.existsSync(path.join(depsDir, \"node_modules\"))) {\n\t\tthrow new Error(`source deps tree has no node_modules (${depsDir}); delete it and retry`);\n\t}\n\t// Shadow-mount every node_modules visible in the host tree (they hold darwin\n\t// binaries) with the skeleton's linux one; both sides of each mount must exist.\n\tconst nodeModules = [\"node_modules\"];\n\tfor (const dir of pkgDirs) {\n\t\tconst rel = path.join(dir, \"node_modules\");\n\t\tconst inHost = fs.existsSync(path.join(REPO_ROOT, rel));\n\t\tconst inDeps = fs.existsSync(path.join(depsDir, rel));\n\t\tif (!inHost && !inDeps) continue;\n\t\tif (!inDeps) fs.mkdirSync(path.join(depsDir, rel), { recursive: true });\n\t\tif (!inHost) fs.mkdirSync(path.join(REPO_ROOT, rel), { recursive: true });\n\t\tnodeModules.push(rel);\n\t}\n\treturn { arch, depsDir, nodeModules };\n}\n\n/**\n * Compose overlay applied to every trial's `main` service: host networking and/or the","sourceCodeStart":1144,"sourceCodeEnd":1180,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/metaharness/src/runner.ts#L1144-L1180","documentation":"After the install step succeeds (or is skipped via the stamp), the runner verifies that node_modules actually exists under the deps dir. If the package manager 'succeeded' without producing node_modules, or the tree was partially deleted, it throws and asks the user to delete the deps dir and retry. This is a post-condition sanity check on the cached dependency tree.","triggerScenarios":"A stale/corrupted deps dir where the stamp file exists but node_modules was removed; an install script that exits 0 without installing (misconfigured package manager); the dir was created but its node_modules deleted by another process.","commonSituations":"Manual cleanup deleted node_modules but left the stamp file; a workspace prune/clean script removed node_modules; switching package managers left an incompatible layout in the cached dir.","solutions":["Delete the deps dir (the path shown in the error) and rerun so everything is installed fresh","Check for stray cleanup scripts or IDE tooling that removes node_modules under that path","Verify the install script for the skeleton actually writes node_modules into depsDir","If using a custom package manager wrapper, confirm it installs into the expected directory"],"exampleFix":"// before: stamp present, node_modules missing\n$ rm -rf <depsDir>\n// after: rerun harness; fresh install recreates node_modules and the stamp","handlingStrategy":"validation","validationCode":"import * as fs from \"node:fs\";\nif (!fs.existsSync(path.join(depsDir, \"node_modules\"))) {\n  fs.rmSync(depsDir, { recursive: true, force: true }); // delete stale tree before rerunning\n}","typeGuard":"function depsTreeHealthy(depsDir: string): boolean {\n  return fs.existsSync(path.join(depsDir, \"node_modules\"));\n}","tryCatchPattern":"try {\n  await runHarness();\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"no node_modules\")) {\n    const dir = err.message.match(/\\((.*)\\)/)?.[1];\n    if (dir) fs.rmSync(dir, { recursive: true, force: true });\n    // then rerun the harness\n  } else throw err;\n}","preventionTips":["Never delete node_modules from the cached deps dir without removing the stamp file too","Exclude the deps dir from repo-wide clean/prune scripts","After any manual cleanup, rerun the harness so stamps and node_modules regenerate together"],"tags":["dependencies","filesystem","corruption"],"backgroundTag":"missing-node-modules","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}