heygen-com/hyperframes · critical · Error

background preview child did not report a PID

Error message

background preview child did not report a PID

What it means

Thrown by startBackgroundPreview after spawn() returns a child whose .pid is falsy. Node sets child.pid synchronously when the OS forks/execs the process; a missing pid means the process was never actually created (e.g. the executable path does not exist or the spawn failed at the OS level before a pid could be assigned).

Source

Thrown at packages/cli/src/commands/previewLifecycle.ts:152

  const logPath = previewLogPath(projectDir, stateHome);
  mkdirSync(dirname(logPath), { recursive: true });
  const logFd = openSync(logPath, "a", 0o600);
  const spawn = dependencies.spawn ?? (nodeSpawn as unknown as SpawnPreview);
  let child: SpawnResult;
  try {
    child = spawn(
      dependencies.execPath ?? process.execPath,
      buildBackgroundPreviewArgs(dependencies.argv ?? process.argv.slice(1)),
      {
        detached: true,
        stdio: ["ignore", logFd, logFd],
        env: process.env,
      },
    );
  } finally {
    closeSync(logFd);
  }
  if (!child.pid) throw new Error("background preview child did not report a PID");
  child.unref();
  return { pid: child.pid, logPath };
}

function startedServer(
  servers: ActiveServer[],
  projectDir: string,
  existing: ActiveServer | null,
  forceNew: boolean,
  browserGpuMode?: BrowserGpuMode,
): ActiveServer | null {
  const candidates =
    forceNew && existing ? servers.filter((server) => server.port !== existing.port) : servers;
  return matchingServer(candidates, projectDir, browserGpuMode);
}

export function buildBackgroundPreviewArgs(argv: string[]): string[] {
  const filtered = argv.filter(

View on GitHub (pinned to c2996c8626)

Solutions

  1. Verify the Node binary is executable: `node -v` and `which node`
  2. Check process limits with `ulimit -u` and raise if at ceiling
  3. If injecting dependencies.execPath in tests/host code, ensure it resolves to a real executable
Defensive patterns

Strategy: retry

Validate before calling

import { existsSync } from "node:fs";
function nodeExecutableOk(p: string): boolean {
  try { return existsSync(p) && (p === process.execPath); } catch { return false; }
}

Try / catch

try {
  await startBackgroundPreview(...);
} catch (e) {
  if (String(e.message).includes("did not report a PID")) {
    // verify node binary + raise process limits, then retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: dependencies.execPath / process.execPath points to a non-existent or non-executable Node binary; the host is at a process/resource limit so fork fails; a broken Node install invoked via a shim that cannot exec. The detached spawn with stdio routed to a log fd succeeds in returning a Child handle but with pid undefined.

Common situations: Running under a container/sandbox that restricts fork; NODE path overridden to a bad value; very low ulimit -u (max processes); a corrupted or relocated Node installation.

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/6cd00be63f69c770. Report an issue: GitHub.