Skip to content

[Bug] vsearch aborts on a missing vec table instead of skipping it (vec_events/vec_context are never created) #161

Description

@J0nd1sk

Summary

brainctl vsearch <query> aborts the entire command with a "no such table" error when any one of its target vec tables is missing — even when other tables (e.g. vec_memories) are present and would return results. By default vsearch searches memories,events,context, but vec_events and vec_context are never created anywhere in the codebase, so the default invocation fails on any brain.db that doesn't happen to have those tables.

Environment

  • brainctl main @ c634808 (version = "2.8.0"); also reproduces on the PyPI 2.8.0 wheel
  • brainctl[vec] installed, sqlite-vec present, Ollama reachable

Reproduction

On a brain.db that has vec_memories populated but no vec_events:

brainctl vsearch "deploy key rotation"

Result:

{
  "error": "Database table missing: no such table: vec_events",
  "hint": "Run 'brainctl init' to create a fresh database, or 'brainctl init --force' to reset."
}

(On a brand-new DB where vec_memories itself is absent, the same failure occurs on the first table instead.) The hint is misleading — brainctl init does not create vec_events/vec_context either.

Root cause

Two compounding problems:

  1. No per-table guard. cmd_vsearch (src/agentmemory/_impl.py:8074) defaults to tables = ["memories", "events", "context"] (_impl.py:8081). Its inner helper _vsearch_table (_impl.py:8091) runs:

    vec_rows = db.execute(
        f"SELECT rowid, distance FROM {vec_table} WHERE embedding MATCH ? AND k=?",
        (q_blob, fetch_n),
    ).fetchall()

    with no handling for a missing {vec_table}. A single absent table raises OperationalError, which the CLI's catch-all turns into the "Database table missing" error — discarding results from the tables that did exist.

  2. vec_events / vec_context are never created or populated. grep -rn "vec_events\|vec_context" src finds only read sites (the vsearch queries) — there is no CREATE VIRTUAL TABLE ... vec_events, and nothing embeds events/context into a vector table. Only vec_memories is ever created (vec.py / _impl.py reindex path). So the events and context branches of the default vsearch are dead.

Suggested fix

  • Make _vsearch_table resilient: catch sqlite3.OperationalError for a missing table and return [] for that source, so vsearch still returns results from the tables that exist (this alone makes brainctl vsearch <q> work against any real DB).
  • Separately, decide the intended behavior for events/context vector search: either implement the indexing (create + populate vec_events/vec_context) or drop them from the default tables set and document them as unsupported. (Filing the resilience fix as the immediate bug; happy to scope the indexing work separately if you'd like it.)

I have the resilience fix + a regression test and will open a PR.

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