paperclipai/paperclip · error

Invalid running embedded database port

Error message

Invalid running embedded database port

What it means

Thrown by create-auth-bootstrap-invite when line 4 of the embedded PostgreSQL postmaster.pid file (the TCP port postmaster is listening on) is not an integer in the valid port range 1-65535. The script trusts this line to build the postgres:// connection URL for the embedded database, so an unusable port means the pid file is stale, corrupt, or from a layout it does not understand, and it aborts instead of connecting to the wrong instance.

Solutions

  1. Confirm the embedded database is running for this exact data directory (start it with `pnpm dev`) so a complete postmaster.pid exists
  2. Delete the stale/truncated postmaster.pid and restart the embedded database so it regenerates a full pid file
  3. Reset the embedded data directory if it is expendable: `rm -rf data/pglite && pnpm dev`, then rerun the script
  4. Switch the config to database.mode "postgres" with a connectionString to bypass pid-file parsing entirely

Example fix

// inspect the pid file
// cat ./data/pglite/postmaster.pid  # line 1=PID, 2=datadir, 4=port
// before (config.json)
{ "database": { "mode": "embedded", "embeddedPostgresDataDir": "./stale-dir" } }
// after
{ "database": { "mode": "embedded", "embeddedPostgresDataDir": "./data/pglite" } }
Defensive patterns

Strategy: validation

Validate before calling

import { readFileSync } from "node:fs";
const pidLines = readFileSync(`${dataDir}/postmaster.pid`, "utf8").split(/\r?\n/);
const port = Number(pidLines[3]);
if (!Number.isInteger(port) || port < 1 || port > 65535) {
  throw new Error(`postmaster.pid line 4 is not a valid port: ${pidLines[3]}`);
}

Type guard

function isValidPort(v: unknown): v is number {
  return typeof v === "number" && Number.isInteger(v) && v >= 1 && v <= 65535;
}

Try / catch

try {
  await runBootstrapInvite(configPath, baseUrl);
} catch (err) {
  if (err instanceof Error && err.message === "Invalid running embedded database port") {
    // pid file truncated/stale: restart embedded postgres, then retry
    await restartEmbeddedPostgres(dataDir);
    await runBootstrapInvite(configPath, baseUrl);
  } else throw err;
}

Prevention

When it happens

Trigger: Running the bootstrap script in embedded mode (config.database.mode !== "postgres") where <embeddedPostgresDataDir>/postmaster.pid has fewer than 5 lines (so pidLines[3] is undefined) or a fourth line that Number() cannot turn into an integer between 1 and 65535.

Common situations: Embedded Postgres crashed mid-write leaving a truncated pid file; the data directory belongs to an older/different PostgreSQL layout; a leftover pid file from an instance that already exited; pointing embeddedPostgresDataDir at a partially initialized or manually copied directory.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/044c96a4ace7c353. Report an issue: GitHub.

Appendix: source

Thrown at packages/db/scripts/create-auth-bootstrap-invite.ts:50

      mode?: string;
      embeddedPostgresPort?: number;
      embeddedPostgresDataDir?: string;
      connectionString?: string;
    };
  };
  // The server can select another port when the configured one is occupied.
  // Bind bootstrap to this data directory's running process, never another instance.
  let embeddedPort: number | undefined;
  if (config.database?.mode !== "postgres") {
    const dataDir = config.database?.embeddedPostgresDataDir;
    if (!dataDir) throw new Error("Embedded bootstrap requires its configured data directory");
    const pidLines = readFileSync(path.join(dataDir, "postmaster.pid"), "utf8").split(/\r?\n/);
    if (realpathSync(pidLines[1] ?? "") !== realpathSync(dataDir)) throw new Error("Embedded bootstrap data directory does not match the running postmaster");
    const postmasterPid = Number(pidLines[0]);
    if (!Number.isInteger(postmasterPid) || postmasterPid <= 1) throw new Error("Invalid embedded postmaster PID");
    process.kill(postmasterPid, 0);
    embeddedPort = Number(pidLines[3]);
    if (!Number.isInteger(embeddedPort) || embeddedPort < 1 || embeddedPort > 65535) throw new Error("Invalid running embedded database port");
  }
  const dbUrl =
    config.database?.mode === "postgres"
      ? config.database.connectionString
      : `postgres://paperclip:paperclip@127.0.0.1:${embeddedPort}/paperclip`;
  if (!dbUrl) {
    throw new Error(`Could not resolve database connection from ${configPath}`);
  }

  const db = createDb(dbUrl);
  const closableDb = db as typeof db & {
    $client?: {
      end?: (options?: { timeout?: number }) => Promise<void>;
    };
  };

  try {
    const now = new Date();

View on GitHub (pinned to 3f1d897a7c)