MemPalace/mempalace · error · DimensionMismatchError

sqlite_exact collection {self._collection_name!r} expects em

Error message

sqlite_exact collection {self._collection_name!r} expects embedding dimension {expected_dim}, got {int(q.size)}

What it means

Raised during query/search on a sqlite_exact collection: a query embedding's dimension does not match the dimension recorded for the collection. Unlike the write-side checks, this fires per query vector, after rows are loaded — the guard sits inside the query loop right before cosine scoring so the failure names the exact expected vs received sizes.

Source

Thrown at mempalace/backends/sqlite_exact.py:612

            raise ValueError("query input must be a non-empty list")

        spec = _IncludeSpec.resolve(include, default_distances=True)
        outer_ids: list[list[str]] = []
        outer_docs: list[list[str]] = []
        outer_metas: list[list[dict]] = []
        outer_dists: list[list[float]] = []
        outer_embeds: list[list[list[float]]] = []

        with self._cursor() as cur:
            collection_id = self._collection_id(cur)
            expected_dim = self._collection_dimension(cur, collection_id)
            rows = self._rows(cur, where=where, where_document=where_document)
            row_vectors = [(row, _decode_array(row["embedding"])) for row in rows]

        for query_vector in query_embeddings:
            q = _as_vector_array(query_vector)
            if expected_dim is not None and int(q.size) != expected_dim:
                raise DimensionMismatchError(
                    f"sqlite_exact collection {self._collection_name!r} expects "
                    f"embedding dimension {expected_dim}, got {int(q.size)}"
                )
            q_norm = float(np.linalg.norm(q))
            scored = []
            for row, vec in row_vectors:
                if vec is None or vec.size != q.size:
                    continue
                denom = q_norm * float(np.linalg.norm(vec))
                cos = 0.0 if denom <= 0 else float(np.dot(q, vec) / denom)
                distance = 1.0 - max(-1.0, min(1.0, cos))
                scored.append((distance, row, vec))
            scored.sort(key=lambda item: item[0])
            top = scored[:n_results]

            outer_ids.append([row["id"] for _, row, _ in top])
            outer_docs.append([row["document"] for _, row, _ in top] if spec.documents else [])
            outer_metas.append([row["metadata"] for _, row, _ in top] if spec.metadatas else [])

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Compute query embeddings with the same model used at ingest — check `col.get_stored_embedder_identity()` and match it.
  2. If you must change models, rebuild/re-ingest the collection (see DimensionMismatchError on write) so both sides share one dimension.
  3. Pre-validate before querying: `assert len(qvec) == expected_dim` where expected_dim comes from the collection metadata.

Example fix

# before
# collection built with 768-dim model
results = col.query(query_embeddings=[embed_large("query")], n_results=5)  # 1536-dim

# after
results = col.query(query_embeddings=[embed_small("query")], n_results=5)  # 768-dim, same model as ingest
Defensive patterns

Strategy: validation

Validate before calling

def validate_query_dim(col, query_embeddings):
    with col._cursor() as cur:
        cid = col._collection_id(cur)
        expected = col._collection_dimension(cur, cid)
    if expected is not None:
        for q in query_embeddings:
            if len(q) != expected:
                raise ValueError(f"query dim {len(q)} != collection dim {expected}; use the ingest embedder")

Try / catch

try:
    col.query(query_embeddings=[qv], n_results=k)
except DimensionMismatchError:
    qv = embed_with_ingest_model(query_text)  # match stored identity
    col.query(query_embeddings=[qv], n_results=k)

Prevention

When it happens

Trigger: Calling query/query_texts with embeddings from a different model than the one that built the collection — e.g. searching a 768-dim palace with 1536-dim query vectors; supplying `query_embeddings` manually computed with the wrong model; a changed default embedder in the searcher between ingest and search.

Common situations: Swapped the local embedding model after building the palace but before searching; a client computes embeddings with a different backend than the ingest pipeline; multiple palaces with different models and the wrong query path taken.

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/0b926e0cf09720a6. Report an issue: GitHub.