RyanCodrai/turbovec · error · RuntimeError

TurboQuantVectorDb not initialized — call create() before in

Error message

TurboQuantVectorDb not initialized — call create() before insert().

What it means

_require_initialized guards all write paths (insert, async_insert, upsert, async_upsert): if the internal index was never created, a RuntimeError is raised instead of silently auto-creating a table. Mirroring LanceDb semantics, callers must call create() first.

Source

Thrown at turbovec-python/python/turbovec/agno.py:467

        else:
            # An embedder or document without an async path at all: keep
            # the sync fallback, but off the event loop.
            await asyncio.to_thread(self._embed_missing, to_embed)

    def _require_initialized(self) -> None:
        """Raise unless create() has run.

        Called before any embedding work, not after it: embedding is the
        expensive part of a write (a paid API call, GPU time), and a write
        into an uninitialized store is doomed from the start. `insert()`
        already failed at this boundary; `async_insert`, `upsert` and
        `async_upsert` embedded first and only discovered it when they
        delegated here (#473).
        """
        if self._index is None:
            # Match LanceDb's "table not initialized" handling: do not
            # silently auto-create. Callers must invoke create() first.
            raise RuntimeError(
                "TurboQuantVectorDb not initialized — call create() before insert()."
            )

    def insert(
        self,
        content_hash: str,
        documents: List[Document],
        filters: Optional[Dict[str, Any]] = None,
    ) -> None:
        if not documents:
            return
        self._require_initialized()

        # Merge `filters` into each document's metadata (matches LanceDb).
        if filters:
            for doc in documents:
                meta = dict(doc.meta_data) if doc.meta_data else {}
                meta.update(filters)

View on GitHub (pinned to ccab9f325e)

Solutions

  1. Call await db.async_create() (or db.create()) before the first insert/upsert.
  2. Wrap write operations with an initialization check: if db._index is None or not db.exists(), create first.
  3. If loading an existing persisted index, use the loader path that initializes _index instead of create().

Example fix

// before
vec_db = TurboQuantVectorDb(embedder=e)
vec_db.insert(docs)  # RuntimeError
// after
vec_db = TurboQuantVectorDb(embedder=e)
if not vec_db.exists():
    vec_db.create()
vec_db.insert(docs)
Defensive patterns

Strategy: try-catch

Validate before calling

if getattr(db, "_index", None) is None and not db.exists():
    db.create()

Type guard

def is_initialized(db) -> bool:
    return db._index is not None

Try / catch

try:
    db.insert(content_hash, documents)
except RuntimeError as e:
    if "not initialized" in str(e):
        db.create()
        db.insert(content_hash, documents)

Prevention

When it happens

Trigger: Calling insert()/upsert() (or their async variants) on a TurboQuantVectorDb instance before create() was called — e.g. constructing the DB and immediately writing documents.

Common situations: Porting code from vector DBs that auto-create tables on first write; skipping create() in a script after adding load(); a constructor path that intentionally defers index creation (lazy init) but callers assume eager init.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of RyanCodrai/turbovec@ccab9f325e (2026-09-06). Data as JSON: /api/errors/5e38ab165a2fa323. Report an issue: GitHub.