paperclipai/paperclip · error · Error

${error instanceof Error ? error.message : String(error)}\n$

Error message

${error instanceof Error ? error.message : String(error)}\n${stderr}

What it means

Thrown by runCommandWithDiagnostics (install.ts:51) to enrich a failed execFile error with its stderr. The wrapper rethrows the original error if stderr is empty or already embedded in the message; otherwise it creates a new Error concatenating message + stderr and chains the original via `cause`.

Source

Thrown at cli/src/commands/install.ts:51

  args: string[],
  options?: Parameters<typeof execFileAsync>[2],
) => Promise<{ stdout: string; stderr: string }>;

type ReleasePackageEntry = { dir: string; name: string };

export async function runCommandWithDiagnostics(
  file: string,
  args: string[],
  options?: Parameters<typeof execFileAsync>[2],
): Promise<{ stdout: string; stderr: string }> {
  try {
    return await execFileAsync(file, args, { ...options, encoding: "utf8" });
  } catch (error) {
    const stderr = error && typeof error === "object" && "stderr" in error && typeof error.stderr === "string"
      ? error.stderr.trim()
      : "";
    if (!stderr || (error instanceof Error && error.message.includes(stderr))) throw error;
    throw new Error(`${error instanceof Error ? error.message : String(error)}\n${stderr}`, { cause: error });
  }
}

export function resolveGitInstallWorkspacePackages(checkoutPath: string): ReleasePackageEntry[] {
  const manifestPath = path.join(checkoutPath, "scripts", "release-package-manifest.json");
  const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8")) as ReleasePackageEntry[];
  const packageByName = new Map(manifest.map((entry) => [entry.name, entry]));
  const visiting = new Set<string>();
  const visited = new Set<string>();
  const ordered: ReleasePackageEntry[] = [];

  const visit = (packageName: string): void => {
    if (visited.has(packageName)) return;
    if (visiting.has(packageName)) throw new Error(`Circular workspace dependency while staging ${packageName}.`);
    const entry = packageByName.get(packageName);
    if (!entry) throw new Error(`Git install cannot stage workspace dependency ${packageName}; it is missing from scripts/release-package-manifest.json.`);
    visiting.add(packageName);
    const packageJson = JSON.parse(fs.readFileSync(path.join(checkoutPath, entry.dir, "package.json"), "utf8")) as Record<string, unknown>;

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Read both layers: the top line (npm/git message) and the appended stderr block.
  2. Address the underlying tool failure (fix lockfile, fix permissions, retry network).
  3. Re-run with the same command after fixing root cause; do not retry unchanged.
  4. Inspect error.cause for the original execFile error if more detail is needed.

Example fix

// before: catch only the surfaced message
try { await run(...) } catch (e) { console.log(e.message) }
// after: also inspect cause and stderr
try { await run(...) } catch (e) { console.log(e.message, e.cause) }
Defensive patterns

Strategy: try-catch

Type guard

function hasExecFileStderr(err: unknown): err is Error & { stderr: string } {
  return !!err && typeof err === "object" && "stderr" in err && typeof (err as any).stderr === "string";
}

Try / catch

try {
  return await runCommandWithDiagnostics(file, args, options);
} catch (err) {
  const detail = err instanceof Error ? err.message : String(err);
  const cause = (err as Error & { cause?: unknown }).cause;
  console.error('Command failed:', detail, '\ncause:', cause);
  throw err;
}

Prevention

When it happens

Trigger: Any child process spawned by the installer (npm, git, node) exits non-zero and produces stderr that is not already part of the error message — e.g. npm install failures, git checkout errors, or shim write failures.

Common situations: npm registry/lockfile errors, git network failures during a --ref install, permission errors writing the managed shim, or missing system dependencies.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/8677a2df05dbacb1. Report an issue: GitHub.