can1357/oh-my-pi · error · Error
Failed to install ${packageName}: ${stderr}
Error message
Failed to install ${packageName}: ${stderr} What it means
installPlugin spawns the package manager to install the requested plugin and waits for exit plus collected stdout/stderr. A non-zero exit code throws 'Failed to install <packageName>: <stderr>', surfacing the package manager's stderr as the cause.
Source
Thrown at packages/coding-agent/src/extensibility/plugins/installer.ts:64
// Run npm install in plugins directory
const proc = Bun.spawn(["bun", "install", packageName], {
cwd: PLUGINS_DIR,
stdin: "ignore",
stdout: "pipe",
stderr: "pipe",
windowsHide: true,
});
// Drain both pipes concurrently with proc.exited to avoid a pipe-buffer
// deadlock if bun install floods stdout/stderr.
const [exitCode, , stderr] = await Promise.all([
proc.exited,
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
]);
if (exitCode !== 0) {
throw new Error(`Failed to install ${packageName}: ${stderr}`);
}
// Extract the actual package name (without version specifier) for path lookup
const actualName = extractPackageName(packageName);
// Read the installed package's package.json
const pkgPath = path.join(PLUGINS_DIR, "node_modules", actualName, "package.json");
const pkgFile = Bun.file(pkgPath);
if (!(await pkgFile.exists())) {
throw new Error(`Package installed but package.json not found at ${pkgPath}`);
}
const pkg = await pkgFile.json();
return {
name: pkg.name,
version: pkg.version,
path: path.join(PLUGINS_DIR, "node_modules", actualName),View on GitHub (pinned to 9690622007)
Solutions
- Read the stderr in the message — it contains the package manager's actual reason.
- Verify the package exists: `npm view <packageName>` or check the registry in a browser.
- Check network/proxy access to the registry and any required auth tokens (.npmrc).
- Install manually with `bun add <packageName>` in the plugins dir to reproduce and debug the exact failure.
Example fix
// before: unresolvable version
await installPlugin("omp-plugin@^99.0.0")
// after
await installPlugin("omp-plugin@^1.0.0") Defensive patterns
Strategy: retry
Validate before calling
const view = Bun.spawnSync(["npm", "view", packageName, "version"], { stdout: "pipe", stderr: "pipe" });
if (view.exitCode !== 0) {
throw new Error(`Package not resolvable: ${packageName} (${view.stderr.toString().trim()})`);
}
await installPlugin(packageName); Try / catch
try {
await installPlugin(pkg);
} catch (err) {
if (err instanceof Error && err.message.startsWith("Failed to install")) {
const transient = /ETIMEDOUT|ECONNRESET|network/i.test(err.message);
if (transient) await backoffRetry(() => installPlugin(pkg), 3);
else throw new Error(`Install failed permanently: ${err.message}`);
} else throw err;
} Prevention
- Verify the package exists in the registry before installing
- Ensure registry auth tokens (.npmrc) and proxy settings are present in CI
- Use exact or known-good version ranges to avoid unresolvable specifiers
When it happens
Trigger: bun/npm install exits non-zero: package doesn't exist in the registry, no network, version specifier unresolvable, auth required for a private registry, or peer-dependency conflicts.
Common situations: Typo'd package name (404 Not Found); offline/CI without registry access; private registry packages without an auth token; incompatible engine/version constraints; proxy blocks registry.npmjs.org.
Related errors
- bun pm cache failed: ${cacheResult.stderr}
- Failed to refresh Bun's git cache for ${source.host}/${sourc
- timed out: {command}
- V2 remote compaction failed (${response.status} ${response.s
- V2 compaction stream closed before response.completed
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/80516fb0456a5a39.
Report an issue: GitHub.