{"record":{"id":"964d3545081db738","repo":"paperclipai/paperclip","slug":"invalid-embedded-postmaster-pid","errorCode":null,"errorMessage":"Invalid embedded postmaster PID","messagePattern":"Invalid embedded postmaster PID","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/db/scripts/create-auth-bootstrap-invite.ts","lineNumber":47,"sourceCode":"\n  const config = JSON.parse(readFileSync(path.resolve(configPath), \"utf8\")) as {\n    database?: {\n      mode?: string;\n      embeddedPostgresPort?: number;\n      embeddedPostgresDataDir?: string;\n      connectionString?: string;\n    };\n  };\n  // The server can select another port when the configured one is occupied.\n  // Bind bootstrap to this data directory's running process, never another instance.\n  let embeddedPort: number | undefined;\n  if (config.database?.mode !== \"postgres\") {\n    const dataDir = config.database?.embeddedPostgresDataDir;\n    if (!dataDir) throw new Error(\"Embedded bootstrap requires its configured data directory\");\n    const pidLines = readFileSync(path.join(dataDir, \"postmaster.pid\"), \"utf8\").split(/\\r?\\n/);\n    if (realpathSync(pidLines[1] ?? \"\") !== realpathSync(dataDir)) throw new Error(\"Embedded bootstrap data directory does not match the running postmaster\");\n    const postmasterPid = Number(pidLines[0]);\n    if (!Number.isInteger(postmasterPid) || postmasterPid <= 1) throw new Error(\"Invalid embedded postmaster PID\");\n    process.kill(postmasterPid, 0);\n    embeddedPort = Number(pidLines[3]);\n    if (!Number.isInteger(embeddedPort) || embeddedPort < 1 || embeddedPort > 65535) throw new Error(\"Invalid running embedded database port\");\n  }\n  const dbUrl =\n    config.database?.mode === \"postgres\"\n      ? config.database.connectionString\n      : `postgres://paperclip:paperclip@127.0.0.1:${embeddedPort}/paperclip`;\n  if (!dbUrl) {\n    throw new Error(`Could not resolve database connection from ${configPath}`);\n  }\n\n  const db = createDb(dbUrl);\n  const closableDb = db as typeof db & {\n    $client?: {\n      end?: (options?: { timeout?: number }) => Promise<void>;\n    };\n  };","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/db/scripts/create-auth-bootstrap-invite.ts#L29-L65","documentation":"This error is thrown by the create-auth-bootstrap-invite bootstrap script when it parses the embedded PostgreSQL postmaster.pid file and the first line (the PID) is not a usable integer greater than 1. The script must signal the running postmaster (process.kill(pid, 0)) to prove the embedded database is alive before binding the invite creation to it; a malformed PID means the pid file is corrupt, empty, or from a different format, so it refuses to continue rather than killing or connecting to the wrong process.","triggerScenarios":"Running `tsx create-auth-bootstrap-invite.ts --config <path> --base-url <url>` against a config whose database.mode is not \"postgres\" (embedded mode) where the file <embeddedPostgresDataDir>/postmaster.pid exists but its first line, when passed to Number(), is NaN, non-integer, zero, or negative (or 1).","commonSituations":"Embedded Postgres was never started so an empty or leftover postmaster.pid exists; the data directory was copied or restored and the pid file is truncated; a stale/corrupt pid file left after an unclean shutdown; the config points at a directory that contains a partial or hand-edited postmaster.pid; the database mode was switched between embedded and postgres without cleaning the data dir.","solutions":["Ensure the embedded Postgres for this data directory is actually running (start the dev server with `pnpm dev`) before running the bootstrap script","Stop everything, delete the stale postmaster.pid (or reset the data dir with `rm -rf data/pglite && pnpm dev` if acceptable), and let a fresh postmaster rewrite it","Verify the config's database.embeddedPostgresDataDir points at the real live data directory, not a copy, backup, or empty folder","If you need no embedded database, set database.mode to \"postgres\" with a connectionString so the pid file is not consulted at all"],"exampleFix":"// before (config.json)\n{ \"database\": { \"mode\": \"embedded\", \"embeddedPostgresDataDir\": \"./backup/pglite-copy\" } }\n// after\n{ \"database\": { \"mode\": \"embedded\", \"embeddedPostgresDataDir\": \"./data/pglite\" } }\n// and start the embedded database first:\n// pnpm dev","handlingStrategy":"validation","validationCode":"import { readFileSync } from \"node:fs\";\nconst pidLines = readFileSync(`${dataDir}/postmaster.pid`, \"utf8\").split(/\\r?\\n/);\nconst pid = Number(pidLines[0]);\nif (!Number.isInteger(pid) || pid <= 1) throw new Error(\"postmaster.pid has no valid PID; start the embedded database first\");\nprocess.kill(pid, 0); // throws ESRCH if the process is gone","typeGuard":"function isValidPid(v: unknown): v is number {\n  return typeof v === \"number\" && Number.isInteger(v) && v > 1;\n}","tryCatchPattern":"try {\n  await runBootstrapInvite(configPath, baseUrl);\n} catch (err) {\n  if (err instanceof Error && err.message === \"Invalid embedded postmaster PID\") {\n    // regenerate the pid file, then retry once\n    await startEmbeddedPostgres(dataDir);\n    await runBootstrapInvite(configPath, baseUrl);\n  } else throw err;\n}","preventionTips":["Always start the dev server (pnpm dev) so embedded Postgres writes a fresh postmaster.pid before running bootstrap scripts","Never hand-edit or copy postmaster.pid; treat the data directory as owned by the postmaster","Reset expendable embedded data dirs (rm -rf data/pglite) instead of restoring partial backups","If you do not need embedded mode, configure database.mode=postgres with a connectionString"],"tags":["database","embedded-postgres","config","process"],"backgroundTag":"invalid-config-value","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}