Skip to content

gbrain dream — all DB-dependent phases fail with "connect() has not been called" #1404

@SkyairOnline

Description

@SkyairOnline

gbrain version: 0.41.0.0
Engine: Postgres (local standalone via Homebrew)
Runtime: Bun 1.2.22
OS: macOS (arm64)

Description

Running gbrain dream runs all 17 phases, but every DB-dependent phase fails with "No database connection: connect() has not been called". Filesystem-only phases (lint, backlinks) work fine.

Reproduction

gbrain dream

Output (abbreviated):

  ! lint        0 fix(es) applied, 52 remaining          ← OK (FS-only)
  ✓ backlinks   1 missing back-link(s) found              ← OK (FS-only)
  ✗ sync        sync phase failed                        ← FAIL
      [InternalError/UNKNOWN] No database connection: connect() has not been called.
  ✗ synthesize  synthesize phase failed                  ← FAIL
      ...
  ✓ extract     0 link(s), 0 timeline entries            ← batch writes silently lost
  ✗ embed       embed phase failed                       ← FAIL
  ✗ orphans     orphans phase failed                     ← FAIL
  ...

Key Observations

  1. Each individual phase works fine in isolation:

    gbrain dream --phase sync      # ✅ works
    gbrain dream --phase embed     # ✅ works
    gbrain dream --phase extract   # ✅ works
    gbrain dream --phase orphans   # ✅ works
  2. gbrain doctor connects fine — all 47 checks pass, 100/100 score.

  3. gbrain init --url <url> connects fine — schema migration succeeds.

  4. Programmatic runCycle(engine, ...) also fails when running all phases, but a single-phase (['extract']) run works.

  5. GBRAIN_POOL_SIZE=2 doesn't help — the CLI's toEngineConfig() doesn't pass poolSize to the engine config, so the engine always runs in module mode relying on the global db.sql singleton.

Root Cause Analysis

The error originates from src/core/db.ts:getConnection():

export function getConnection() {
  if (!sql) {
    throw new GBrainError(
      'No database connection',
      'connect() has not been called',
      ...
    );
  }
  return sql;
}

The module-level sql variable is set by connect() at startup but becomes null by the time any DB phase executes in the full cycle. Individual phases (separate process) work because each gets a fresh module instance.

Likely cause: The full cycle uses ~20 dynamic await import(...) calls for phase implementations. In some runtime configurations, these dynamic imports can create separate module scopes for db.ts, causing the sql variable to be shadowed or cleared. The PostgresEngine.sql getter and db.getConnection() both check a module-level sql that's null in a different module scope.

Affected code paths

  • src/core/postgres-engine.ts:120get sql() falls back to db.getConnection()
  • src/core/db.ts:151-156getConnection() throws when sql is null
  • src/core/cycle.ts — full cycle with 17 phases, uses await import() for each phase module
  • src/cli.ts:1007-1020 — dream handler: connectEngine()runDream(eng)disconnect()

Workaround

Run individual maintenance steps directly — they all work:

gbrain sync --repo ~/brain
gbrain embed --stale
gbrain check-backlinks fix ~/brain
gbrain lint
gbrain extract all

Suggested Fix

  1. Have PostgresEngine.connect() always create this._sql (instance connection) instead of relying on the module-level db.sql singleton, OR
  2. Ensure dynamic imports in the cycle don't trigger re-initialization of module-level state, OR
  3. Re-check db.sql freshness before each phase and reconnect if stale.

Full diagnostic data

  • gbrain doctor --json: all 47 checks pass, 100/100 score
  • gbrain config show: engine=postgres, database_url=postgresql://localhost:5432/gbrain
  • Fresh re-init + re-import confirmed the bug is not data/config-dependent
  • Migrations: all 89 applied, schema v93 (latest)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions