can1357/oh-my-pi · error · Error

source deps tree has no node_modules (${depsDir}); delete it

Error message

source deps tree has no node_modules (${depsDir}); delete it and retry

What it means

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.

Source

Thrown at packages/metaharness/src/runner.ts:1162

						`linux/${arch === "x64" ? "amd64" : "arm64"}`,
						"-e",
						"HOME=/tmp",
						"-v",
						`${depsDir}:/deps`,
						image,
						"sh",
						"-c",
						script,
					];
		const r = spawnSync(runArgv[0], runArgv.slice(1), { stdio: ["ignore", "inherit", "inherit"] });
		if (r.status !== 0) {
			fs.rmSync(stampFile, { force: true });
			throw new Error(`source deps install failed (${runArgv[0]} exit ${r.status})`);
		}
		fs.writeFileSync(stampFile, `${stamp}\n`);
	}
	if (!fs.existsSync(path.join(depsDir, "node_modules"))) {
		throw new Error(`source deps tree has no node_modules (${depsDir}); delete it and retry`);
	}
	// Shadow-mount every node_modules visible in the host tree (they hold darwin
	// binaries) with the skeleton's linux one; both sides of each mount must exist.
	const nodeModules = ["node_modules"];
	for (const dir of pkgDirs) {
		const rel = path.join(dir, "node_modules");
		const inHost = fs.existsSync(path.join(REPO_ROOT, rel));
		const inDeps = fs.existsSync(path.join(depsDir, rel));
		if (!inHost && !inDeps) continue;
		if (!inDeps) fs.mkdirSync(path.join(depsDir, rel), { recursive: true });
		if (!inHost) fs.mkdirSync(path.join(REPO_ROOT, rel), { recursive: true });
		nodeModules.push(rel);
	}
	return { arch, depsDir, nodeModules };
}

/**
 * Compose overlay applied to every trial's `main` service: host networking and/or the

View on GitHub (pinned to 9690622007)

Solutions

  1. Delete the deps dir (the path shown in the error) and rerun so everything is installed fresh
  2. Check for stray cleanup scripts or IDE tooling that removes node_modules under that path
  3. Verify the install script for the skeleton actually writes node_modules into depsDir
  4. If using a custom package manager wrapper, confirm it installs into the expected directory

Example fix

// before: stamp present, node_modules missing
$ rm -rf <depsDir>
// after: rerun harness; fresh install recreates node_modules and the stamp
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from "node:fs";
if (!fs.existsSync(path.join(depsDir, "node_modules"))) {
  fs.rmSync(depsDir, { recursive: true, force: true }); // delete stale tree before rerunning
}

Type guard

function depsTreeHealthy(depsDir: string): boolean {
  return fs.existsSync(path.join(depsDir, "node_modules"));
}

Try / catch

try {
  await runHarness();
} catch (err) {
  if (err instanceof Error && err.message.includes("no node_modules")) {
    const dir = err.message.match(/\((.*)\)/)?.[1];
    if (dir) fs.rmSync(dir, { recursive: true, force: true });
    // then rerun the harness
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/504055fb9e6a5ab6. Report an issue: GitHub.