Skip to content

/sync-gbrain capability check fails under PgBouncer transaction mode (put succeeds, search returns 'No results') #1435

@agile-operators

Description

@agile-operators

Repro

On a Mac with gbrain v0.27.0 configured against a postgres engine over PgBouncer (transaction mode, port 6543):

$ SLUG="syncprobe59380"
$ echo "ping" | gbrain put "$SLUG"
# (no visible error, exit 0)

$ gbrain search "$SLUG"
No results.

$ gbrain delete "$SLUG"
{
  "status": "soft_deleted",
  "slug": "syncprobe59380",
  "recoverable_until": "now + 72h via restore_page"
}

The page was clearly stored — gbrain delete found and soft-deleted it. But gbrain search returned "No results" for the same slug immediately after the put.

Every gbrain invocation also prints this header:

[gbrain] Prepared statements disabled (PgBouncer transaction-mode convention on port 6543). Override with GBRAIN_PREPARE=true if your pooler runs in session mode.

gbrain doctor --fast reports OK, so this isn't visible to gstack's normal probes. The /sync-gbrain skill's CAPABILITY_OK check (put + search round-trip) correctly drops to 0 and skips writing the ## GBrain Search Guidance block, but the underlying capability is broken and silent under doctor --fast.

Why this matters for gstack

/sync-gbrain Step 4 (capability check) is what gates the ## GBrain Search Guidance block in CLAUDE.md. With this bug, the block never gets written on machines using a transaction-mode PgBouncer pooler — even when memory + brain-sync stages succeed. Agents on those machines never learn to prefer gbrain search over Grep, defeating the point of the integration.

Likely cause (guess, not confirmed)

The search index (tsvector or embedding-based) appears to not update synchronously after a gbrain put under transaction-mode pooling. Delete works because it looks up by slug, but search requires an index lookup that either:

  1. Requires prepared statements (which were disabled), or
  2. Runs in a deferred/async pass that's not triggered before the next CLI call, or
  3. Writes to a different source/index than the put.

The [gbrain] Prepared statements disabled warning hints at (1). The GBRAIN_PREPARE=true override mentioned in the warning is not exposed through any gstack env or config — users hitting this have no documented escape hatch.

Suggested fixes (any of)

  1. Pass GBRAIN_PREPARE=true through gstack env when the user is on a postgres engine over port 6543 — or whenever gstack detects the prepared-statements warning. Document this in /setup-gbrain.
  2. Make gbrain doctor exercise the full put → search → delete round-trip (not just --fast), so this is visible in standard health output. Right now the only way to detect it is /sync-gbrain's capability probe.
  3. If search really does need prepared statements under transaction-mode pooling, surface a clear setup error during /setup-gbrain instead of letting subsequent skills mysteriously fail to write the guidance block.

Environment

  • gstack v1.26.4.0
  • gbrain v0.27.0 (postgres engine)
  • Pooler: PgBouncer, transaction mode, port 6543
  • macOS

Related

Companion issue filed separately: #1434 (code source ID exceeds 32-char limit). Both surfaced in the same /sync-gbrain run.

Filed via Claude Code at the user's request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions