paperclipai/paperclip · critical
The running embedded PostgreSQL identity does not match…
Error message
The running embedded PostgreSQL identity does not match this instance. Startup stopped before connecting.
What it means
embeddedPostgresOwnerPort reads the embedded PostgreSQL postmaster PID file and returns the actual port the running instance is listening on after collision avoidance. Before returning, it verifies that the PID, data directory, and port recorded in the file match the current instance's expected PID and dataDir. Any mismatch or out-of-range port means the running PostgreSQL belongs to a different instance, so startup is stopped before connecting to avoid operating on a foreign database.
Solutions
- Stop the other running Paperclip/PostgreSQL process, then remove the stale postmaster.pid from the data directory before restarting
- Point this instance at its own data directory (or reset dev DB with `rm -rf data/pglite` and `pnpm dev`)
- If the PID file is corrupt (port NaN), delete the pid file only after confirming no postgres process is alive (`ps aux | grep postgres`)
- Run each instance from a distinct workspace/checkout so data dirs do not collide
Example fix
# before: stale pid file from another instance rm -rf data/pglite && pnpm dev
Defensive patterns
Strategy: try-catch
Validate before calling
const contents = fs.readFileSync(postmasterPidFile, "utf8");
const [pid, dir, , port] = contents.split("\n");
const ok = Number(pid) === expectedPid && dir && resolve(dir) === resolve(dataDir)
&& Number.isSafeInteger(Number(port)) && Number(port) >= 1 && Number(port) <= 65535;
if (!ok) console.error("pid file identity mismatch — clean up before starting"); Type guard
function pidFileMatches(contents: string, dataDir: string, expectedPid: number): boolean {
const [pid, directory, , portText] = contents.split("\n");
const port = Number(portText);
return Number(pid) === expectedPid && Boolean(directory)
&& resolve(directory) === resolve(dataDir)
&& Number.isSafeInteger(port) && port >= 1 && port <= 65535;
} Try / catch
try { port = embeddedPostgresOwnerPort(contents, dataDir, expectedPid); }
catch (e) {
console.error("Embedded PostgreSQL identity mismatch; stop the other instance and clear the stale postmaster.pid", e);
process.exit(1);
} Prevention
- Run only one Paperclip instance per data directory
- Stop old instances cleanly so postmaster.pid is removed
- Never hand-edit or copy postmaster.pid files between workspaces
- Reset the dev DB (`rm -rf data/pglite`) when switching branches with schema changes
When it happens
Trigger: Calling startServerWithDatabaseTeardown when a postmaster.pid file exists but records a different PID than expected, a data directory path that resolves elsewhere than the configured dataDir, or a port outside 1-65535 (including NaN from a corrupt/truncated pid file).
Common situations: Copying or restoring a data/ directory while another Paperclip instance is still running; a stale or hand-edited postmaster.pid; running two instances against the same checkout after a crash; Docker volume reuse across differently-configured containers.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Refusing to reuse PostgreSQL: its data directory belongs to…
- Database mode is postgres but no connection string was set…
- Cannot seed target embedded PostgreSQL at
- CLI auth challenge was cancelled.
- database-contract-unmet
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/afa6edcd821b29b7.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/embedded-postgres-owner.ts:10
import { resolve } from "node:path";
/** postmaster.pid records the actual listening port, which can differ from the
* configured port after collision avoidance. Never reuse the configured port. */
export function embeddedPostgresOwnerPort(contents: string, dataDir: string, expectedPid: number): number {
const [pid, directory, , portText] = contents.split("\n");
const port = Number(portText);
if (Number(pid) !== expectedPid || !directory || resolve(directory) !== resolve(dataDir) ||
!Number.isSafeInteger(port) || port < 1 || port > 65535)
throw new Error("The running embedded PostgreSQL identity does not match this instance. Startup stopped before connecting.");
return port;
}
View on GitHub (pinned to 3f1d897a7c)