Symptom
$ npx @cipherstash/cli db install
Error: Invalid stash.config.ts
- databaseUrl: Invalid input: expected nonoptional, received undefined
The error fires even when stash.config.ts plainly sets databaseUrl from process.env.DATABASE_URL. Adding a console.log(process.env.DATABASE_URL) to the config prints the URL just before the error fires.
Reproduces with npx, bunx, pnpm dlx, and db push/db validate/db status/db test-connection/schema build.
Reproducer
// stash.config.ts
import { defineConfig } from '@cipherstash/cli'
export default defineConfig({
databaseUrl: process.env.DATABASE_URL,
client: './src/encryption/index.ts',
})
DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:54322/postgres \
npx @cipherstash/cli db install
Affected versions
@cipherstash/cli 0.7.0 through 0.9.0 (current at time of writing). Earlier versions had the same code path but db install only started loading stash.config.ts in 0.7.x, which is when this surfaced during normal onboarding.
Root cause
loadStashConfig in packages/cli/src/config/index.ts constructs jiti with interopDefault: true and then calls the async jiti.import():
const jiti = createJiti(configPath, { interopDefault: true })
const rawConfig = await jiti.import(configPath) // ← option silently ignored
In jiti 2.x, the constructor's interopDefault only applies to the deprecated synchronous jiti(id) callable form. The async jiti.import() ignores it and always returns the full module namespace. So for export default defineConfig({...}), rawConfig is { default: { databaseUrl, client } }. Zod then validates the wrapper, finds no top-level databaseUrl, and emits the misleading "received undefined" error.
The fix is the per-call { default: true } option, which jiti 2.x's async API does honour.
Symptom
The error fires even when
stash.config.tsplainly setsdatabaseUrlfromprocess.env.DATABASE_URL. Adding aconsole.log(process.env.DATABASE_URL)to the config prints the URL just before the error fires.Reproduces with
npx,bunx,pnpm dlx, anddb push/db validate/db status/db test-connection/schema build.Reproducer
Affected versions
@cipherstash/cli0.7.0 through 0.9.0 (current at time of writing). Earlier versions had the same code path butdb installonly started loadingstash.config.tsin 0.7.x, which is when this surfaced during normal onboarding.Root cause
loadStashConfiginpackages/cli/src/config/index.tsconstructsjitiwithinteropDefault: trueand then calls the asyncjiti.import():In jiti 2.x, the constructor's
interopDefaultonly applies to the deprecated synchronousjiti(id)callable form. The asyncjiti.import()ignores it and always returns the full module namespace. So forexport default defineConfig({...}),rawConfigis{ default: { databaseUrl, client } }. Zod then validates the wrapper, finds no top-leveldatabaseUrl, and emits the misleading "received undefined" error.The fix is the per-call
{ default: true }option, which jiti 2.x's async API does honour.