Fix embedded Postgres initdb failure in Docker slim containers

The embedded-postgres library hardcodes --lc-messages=en_US.UTF-8 and
strips the parent process environment when spawning initdb/postgres.
In slim Docker images (e.g. node:20-bookworm-slim), the en_US.UTF-8
locale isn't installed, causing initdb to exit with code 1.

Two fixes applied:
1. Add --lc-messages=C to all initdbFlags arrays (overrides the
   library's hardcoded locale since our flags come after in the spread)
2. pnpm patch on embedded-postgres to preserve process.env in spawn
   calls, preventing loss of PATH, LD_LIBRARY_PATH, and other vars

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
dotta 2026-03-24 08:03:04 -05:00
parent 59e29afab5
commit 5602576ae1
11 changed files with 38 additions and 11 deletions

View file

@ -63,7 +63,7 @@ async function startTempDatabase() {
password: "paperclip",
port,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: () => {},
onError: () => {},
});

View file

@ -756,7 +756,7 @@ async function ensureEmbeddedPostgres(dataDir: string, preferredPort: number): P
password: "paperclip",
port,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: () => {},
onError: () => {},
});

View file

@ -35,8 +35,8 @@
"test:release-smoke:headed": "npx playwright test --config tests/release-smoke/playwright.config.ts --headed"
},
"devDependencies": {
"cross-env": "^10.1.0",
"@playwright/test": "^1.58.2",
"cross-env": "^10.1.0",
"esbuild": "^0.27.3",
"typescript": "^5.7.3",
"vitest": "^3.0.5"
@ -44,5 +44,10 @@
"engines": {
"node": ">=20"
},
"packageManager": "pnpm@9.15.4"
"packageManager": "pnpm@9.15.4",
"pnpm": {
"patchedDependencies": {
"embedded-postgres@18.1.0-beta.16": "patches/embedded-postgres@18.1.0-beta.16.patch"
}
}
}

View file

@ -67,7 +67,7 @@ async function createTempDatabase(): Promise<string> {
password: "paperclip",
port,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: () => {},
onError: () => {},
});

View file

@ -150,7 +150,7 @@ async function ensureEmbeddedPostgresConnection(
password: "paperclip",
port: selectedPort,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: () => {},
onError: () => {},
});

View file

@ -0,0 +1,22 @@
diff --git a/dist/index.js b/dist/index.js
index ccfe17a82f4879bf20cc345c579a987d9eba5309..dd689f5908f625f49b4785318daea736aa88927f 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -133,7 +133,7 @@ class EmbeddedPostgres {
`--pwfile=${passwordFile}`,
`--lc-messages=${LC_MESSAGES_LOCALE}`,
...this.options.initdbFlags,
- ], Object.assign(Object.assign({}, permissionIds), { env: { LC_MESSAGES: LC_MESSAGES_LOCALE } }));
+ ], Object.assign(Object.assign({}, permissionIds), { env: Object.assign(Object.assign({}, process.env), { LC_MESSAGES: LC_MESSAGES_LOCALE }) }));
// Connect to stderr, as that is where the messages get sent
(_a = process.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (chunk) => {
// Parse the data as a string and log it
@@ -177,7 +177,7 @@ class EmbeddedPostgres {
'-p',
this.options.port.toString(),
...this.options.postgresFlags,
- ], Object.assign(Object.assign({}, permissionIds), { env: { LC_MESSAGES: LC_MESSAGES_LOCALE } }));
+ ], Object.assign(Object.assign({}, permissionIds), { env: Object.assign(Object.assign({}, process.env), { LC_MESSAGES: LC_MESSAGES_LOCALE }) }));
// Connect to stderr, as that is where the messages get sent
(_a = this.process.stderr) === null || _a === void 0 ? void 0 : _a.on('data', (chunk) => {
// Parse the data as a string and log it

View file

@ -72,7 +72,7 @@ async function startTempDatabase() {
password: "paperclip",
port,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: () => {},
onError: () => {},
});

View file

@ -68,7 +68,7 @@ async function startTempDatabase() {
password: "paperclip",
port,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: () => {},
onError: () => {},
});

View file

@ -130,7 +130,7 @@ async function startTempDatabase() {
password: "paperclip",
port,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: () => {},
onError: () => {},
});

View file

@ -76,7 +76,7 @@ async function startTempDatabase() {
password: "paperclip",
port,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: () => {},
onError: () => {},
});

View file

@ -347,7 +347,7 @@ export async function startServer(): Promise<StartedServer> {
password: "paperclip",
port,
persistent: true,
initdbFlags: ["--encoding=UTF8", "--locale=C"],
initdbFlags: ["--encoding=UTF8", "--locale=C", "--lc-messages=C"],
onLog: appendEmbeddedPostgresLog,
onError: appendEmbeddedPostgresLog,
});