Skip to content

bug: CLI database commands conflict with a running LadybugDB gateway #1683

Open

Description

@donovan-yohan

Bug description

With the CGC Gateway running against the embedded LadybugDB backend, direct CLI commands that open the same database fail because the gateway already owns Ladybug's exclusive read-write database lock.

This makes cgc update incompatible with a persistent local gateway even though update is documented as a normal, hook-friendly refresh command. The same conflict affects other direct CLI commands such as cgc list and cgc stats.

Ladybug's lock is expected safety behavior. The integration problem is that the CLI opens a second database object instead of delegating to the gateway that already owns the database, and the resulting error suggests cgc doctor rather than identifying the active gateway.

Steps to reproduce

  1. Configure CGC to use an on-disk LadybugDB database.

  2. Start the gateway:

    cgc api start --host 127.0.0.1 --port 8765
  3. In another terminal, run:

    cgc update /absolute/path/to/an/indexed/repository

Actual behavior

Updating repository index...
Resolving context...
Initializing services and database connection...
Database Connection Error: IO exception: Could not set lock on file :
~/.codegraphcontext/global/db/ladybugdb
(Error: Resource temporarily unavailable)
Please ensure your database is configured correctly or run 'cgc doctor'.

The gateway remains healthy and can access the database through MCP/HTTP because it owns the existing Ladybug Database object.

Expected behavior

Preferably, database-backed CLI operations should detect and delegate to the active local gateway so all operations share its Ladybug database object.

If transparent delegation is intentionally out of scope, the CLI should at least detect this lock conflict and return an actionable error explaining that another CGC process owns the embedded database, rather than suggesting database misconfiguration or cgc doctor.

The Git hook workflow also needs a compatible path: cgc update --quiet cannot refresh a LadybugDB index while a persistent gateway owns the database.

Root cause in current source

  • src/codegraphcontext/cli/main.py: update() calls update_helper().
  • src/codegraphcontext/cli/cli_helpers.py: update_helper() aliases reindex_helper().
  • reindex_helper() calls _initialize_services(), which creates and opens a new database manager/driver.
  • Ladybug permits one read-write Database object per on-disk database. The gateway already owns it.

Ladybug documents this restriction and recommends routing concurrent clients through one API-server-owned database object:
https://docs.ladybugdb.com/concurrency/

Environment

  • CodeGraphContext: 0.6.8
  • Ladybug: 0.19.1
  • macOS: 26.4
  • Backend: on-disk ladybugdb
  • Gateway command: cgc api start --host 127.0.0.1 --port 8765

Scope notes

This is not a stale lock: lsof identifies the live gateway process as the lock owner, and gateway MCP requests continue to succeed. Stopping the gateway releases the lock and allows the CLI command to open the database.

Activity

  1. github-actions commented on Aug 31, 2026

    @github-actions
    Contributor

    Hi! 👋 Join our CodeGraphContext Discord channel to collaborate: https://discord.gg/dR4QY32uYQ

  2. donovan-yohan commented on Aug 31, 2026

    @donovan-yohan
    ContributorAuthor

    Opened #1684 with the small, diagnostic-only fix: lock conflicts now explain that another CGC process owns the embedded database and direct users to the Gateway MCP/HTTP interface or stopping the owner. Automatic CLI-to-Gateway delegation remains out of scope for this PR.

  3. Shashankss1205 commented on Sep 2, 2026

    @Shashankss1205
    Collaborator

    Status: the guidance half landed in #1684 — the CLI now explains the lock conflict truthfully instead of pointing at cgc doctor. Keeping this open for the deeper ask (CLI→Gateway delegation), which needs a Gateway discovery mechanism first.

  4. Shashankss1205 commented on Sep 24, 2026

    @Shashankss1205
    Collaborator

    Status update — half of this shipped, half is still open, and I want to be explicit about which is which so the issue doesn't look more resolved than it is.

    Shipped: the actionable error

    cli_helpers.py now detects the lock signature and says what's actually wrong instead of blaming your configuration:

    Another CGC process already has this embedded database open. If a CGC Gateway or watcher is running, use its MCP/HTTP interface or stop it before running database-backed CLI commands.

    That replaces the misleading run 'cgc doctor' suggestion you quoted, which sent you looking for a misconfiguration that didn't exist. Your report is what made that fix specific rather than generic — thank you for including the exact string and the lsof confirmation that it was a live owner rather than a stale lock. That ruled out an entire wrong diagnosis before anyone started.

    Still open: transparent delegation

    The real fix — CLI commands detecting a running gateway and routing through it rather than opening a second Database object — is not done. Keeping this issue open for it, since the error message makes the failure legible but doesn't make the workflow work.

    Your cgc update --quiet git-hook case is the one that motivates it most, and it's the one the error message helps least: a hook can't usefully be told to go stop the gateway.

    Design notes for whoever takes it

    Recording these so the next person doesn't re-derive them:

    1. Discovery has to be cheap and not itself require the database. The gateway's host/port would need to live somewhere the CLI can read without opening the graph — a pidfile or a small state file written by cgc api start is the obvious route. Probing a hardcoded port is not, since --host/--port are user-supplied.
    2. Delegation can't be all-or-nothing. cgc list and cgc stats are reads and map cleanly onto the gateway's existing HTTP surface. cgc update is a write that drives the whole indexing pipeline, and there may be no gateway endpoint that expresses it today. It's fine for the first PR to delegate reads only and keep the clear error for writes — that's a real improvement and a much smaller review.
    3. Falling back must be silent and correct. No gateway running is the common case, and it must stay exactly as fast as it is now. Discovery failure, a stale pidfile, or an unreachable port all need to fall through to opening the database directly, not to an error.
    4. A stale pidfile is the likely bug. A gateway killed with SIGKILL leaves the file behind; the CLI must verify the process is alive and answering before trusting it, or this fix introduces a new failure mode worse than the one it removes.

    Good, precise report — the root-cause trace through update() → update_helper() → reindex_helper() → _initialize_services() meant no one had to find that path themselves.

  5. added
    gssoc:approvedGSSoC validation: counts toward scoring
    level:advancedGSSoC difficulty: 55 pts contributor / 30 mentor
    mentor:Shashankss1205GSSoC mentor attribution: credits reviewing mentor
    type:bugGSSoC type bonus: bug
    on Sep 24, 2026
  6. Shashankss1205 commented on Oct 15, 2026

    @Shashankss1205
    Collaborator

    Maintenance review — 15 October 2026

    Keep this open for gateway-aware CLI routing or an explicit single-owner database policy. Native availability fixes and better lock diagnostics do not make two processes safe writers to one embedded database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    gssoc:approvedGSSoC validation: counts toward scoringlevel:advancedGSSoC difficulty: 55 pts contributor / 30 mentormentor:Shashankss1205GSSoC mentor attribution: credits reviewing mentortype:bugGSSoC type bonus: bug

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions