Summary
On a fresh install (no ~/.gbrain/config.json AND no DATABASE_URL), gbrain init --pglite ignores GBRAIN_EMBEDDING_MODEL and GBRAIN_EMBEDDING_DIMENSIONS env vars. The init silently defaults to OpenAI 1536, even when the user has explicitly set their preferred provider via shell env.
Repro on v0.35.1.0
# Fresh machine, no config.json, no DATABASE_URL
rm -f ~/.gbrain/config.json
rm -rf ~/.gbrain/brain.pglite
# Set env vars expecting them to take effect
export GBRAIN_EMBEDDING_MODEL=lmstudio:text-embedding-nomic-embed-text-v1.5
export GBRAIN_EMBEDDING_DIMENSIONS=768
# Run plain init
gbrain init --pglite
Result: column comes up at vector(1536) with text-embedding-3-large as the configured model. First embed against LM Studio returns 768-dim, sync explodes with expected 1536 dimensions, not 768.
Root cause
loadConfig() at src/core/config.ts:135 early-returns null when neither fileConfig nor dbUrl is set:
if (!fileConfig && !dbUrl) return null;
Env-var merge logic below that early-return (config.ts:153-176) never runs. The init's resolveAIOptions sees null and falls through to gateway defaults. The env vars ARE honored when there's already a config.json or a DATABASE_URL (both make loadConfig return non-null, then the merge step runs) — but not in the env-only cold-start case.
Workaround
Pre-create config.json before running init. After config.json exists, env vars are honored (loadConfig returns non-null, merge step runs, env vars override file).
Suggested fix shapes (any of)
A. Sibling helper loadAIConfig() that reads ONLY embedding/expansion/chat fields from env + file, no inferredEngine logic. Called from resolveAIOptions in addition to loadConfig. Smallest blast radius; doesn't touch any existing call site.
B. loadConfig early-return refactor — extend the gate so AI-related env vars also bypass the early return, returning a partial config with just AI fields populated. Risk: inferredEngine defaults to 'postgres' for PGLite users (config.ts:143-145), which would silently misroute PGLite users to Postgres setup. Needs careful inferredEngine handling.
C. Document the workaround in install docs. Lowest engineering cost but worst DX.
I'd vote (A) — it gives env-only callers parity with config-file callers without modifying the load-config contract that downstream code relies on.
Context
Discovered while reviewing the patch for #203 (config.json-is-ignored case). That fix lands resolveAIOptions reading loadConfig() first, which works for users who HAVE a config.json. The env-only path remains stranded as a separate bug class. Test case 5 in test/init-config-first.test.ts (in the #203 PR) pins the current (limited) behavior so any future fix is loud.
Related issues:
Summary
On a fresh install (no
~/.gbrain/config.jsonAND noDATABASE_URL),gbrain init --pgliteignoresGBRAIN_EMBEDDING_MODELandGBRAIN_EMBEDDING_DIMENSIONSenv vars. The init silently defaults to OpenAI 1536, even when the user has explicitly set their preferred provider via shell env.Repro on v0.35.1.0
Result: column comes up at
vector(1536)withtext-embedding-3-largeas the configured model. First embed against LM Studio returns 768-dim, sync explodes withexpected 1536 dimensions, not 768.Root cause
loadConfig()atsrc/core/config.ts:135early-returns null when neitherfileConfignordbUrlis set:Env-var merge logic below that early-return (config.ts:153-176) never runs. The init's
resolveAIOptionssees null and falls through to gateway defaults. The env vars ARE honored when there's already a config.json or a DATABASE_URL (both makeloadConfigreturn non-null, then the merge step runs) — but not in the env-only cold-start case.Workaround
Pre-create config.json before running init. After config.json exists, env vars are honored (loadConfig returns non-null, merge step runs, env vars override file).
Suggested fix shapes (any of)
A. Sibling helper
loadAIConfig()that reads ONLY embedding/expansion/chat fields from env + file, noinferredEnginelogic. Called fromresolveAIOptionsin addition toloadConfig. Smallest blast radius; doesn't touch any existing call site.B. loadConfig early-return refactor — extend the gate so AI-related env vars also bypass the early return, returning a partial config with just AI fields populated. Risk:
inferredEnginedefaults to'postgres'for PGLite users (config.ts:143-145), which would silently misroute PGLite users to Postgres setup. Needs careful inferredEngine handling.C. Document the workaround in install docs. Lowest engineering cost but worst DX.
I'd vote (A) — it gives env-only callers parity with config-file callers without modifying the load-config contract that downstream code relies on.
Context
Discovered while reviewing the patch for #203 (config.json-is-ignored case). That fix lands
resolveAIOptionsreadingloadConfig()first, which works for users who HAVE a config.json. The env-only path remains stranded as a separate bug class. Test case 5 intest/init-config-first.test.ts(in the #203 PR) pins the current (limited) behavior so any future fix is loud.Related issues: