paperclipai/paperclip · error
Embedded bootstrap data directory does not match the…
Error message
Embedded bootstrap data directory does not match the running postmaster
What it means
The script reads postmaster.pid from the configured data directory and verifies pidLines[1] (the data directory recorded by the postmaster) resolves to the same real path as the configured directory. A mismatch means the PID file belongs to a different instance — e.g. the data dir was moved, symlinked, or the config points at a copy — and the script refuses to touch that process.
Solutions
- Correct config.database.embeddedPostgresDataDir to match the directory the running postmaster actually uses (read pidLines[1] of postmaster.pid).
- Restart the dev server so postmaster.pid is regenerated for the current directory.
- Remove symlinks — configure the real resolved path.
- Delete a stale postmaster.pid only after confirming no postgres process is running, then restart.
Example fix
// before embeddedPostgresDataDir: "./data/pglite-link" // symlink // after embeddedPostgresDataDir: "/abs/path/to/project/data/pglite" // realpath matching postmaster.pid line 2
Defensive patterns
Strategy: validation
Validate before calling
const pid = readFileSync(path.join(dataDir, "postmaster.pid"), "utf8").split(/\r?\n/);
if (realpathSync(pid[1] ?? "") !== realpathSync(dataDir)) throw new Error("postmaster belongs to a different data dir"); Try / catch
try { await main(); } catch (e) {
if (e.message.includes("does not match the running postmaster")) { console.error("restarting dev server to regenerate postmaster.pid"); }
throw e;
} Prevention
- Never move or symlink the embedded data dir while the server is running
- Point config at the realpath of the data directory
- Confirm only one dev instance uses a given data dir
- If the pid file is stale (no live postgres), remove it and restart cleanly
When it happens
Trigger: realpathSync(pidLines[1]) !== realpathSync(dataDir) while reading <dataDir>/postmaster.pid in non-postgres mode.
Common situations: Configured embeddedPostgresDataDir moved/renamed after the server started; data dir accessed via a symlink while postmaster recorded the real path; two dev instances and the config points at the wrong one; stale postmaster.pid copied with the directory.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Embedded bootstrap requires its configured data directory
- Invalid embedded postmaster PID
- Invalid running embedded database port
- CLI auth challenge was cancelled.
- Could not resolve database connection from
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/0148e8a81ab1e04d.
Report an issue: GitHub.
Appendix: source
Thrown at packages/db/scripts/create-auth-bootstrap-invite.ts:45
throw new Error("Usage: tsx create-auth-bootstrap-invite.ts --config <path> --base-url <url>");
}
const config = JSON.parse(readFileSync(path.resolve(configPath), "utf8")) as {
database?: {
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>;View on GitHub (pinned to 3f1d897a7c)