MemPalace/mempalace · error · ValueError

embedding must be a non-empty 1D vector

Error message

embedding must be a non-empty 1D vector

What it means

Raised by the sqlite_exact backend's vector encoder when an embedding passed to add/upsert is not a non-empty 1D sequence of numbers — after conversion to a float32 numpy array it must have ndim == 1 and size > 0. Empty lists, nested lists (2D batches), or None-as-list all fail here before any SQL runs.

Source

Thrown at mempalace/backends/sqlite_exact.py:75

def _json_loads(text: str | None) -> dict:
    if not text:
        return {}
    try:
        value = json.loads(text)
    except json.JSONDecodeError:
        return {}
    return value if isinstance(value, dict) else {}


def _encode_vector(vector: list[float]) -> bytes:
    return _as_vector_array(vector).tobytes()


def _as_vector_array(vector: list[float]) -> np.ndarray:
    arr = np.asarray(vector, dtype=np.float32)
    if arr.ndim != 1 or arr.size == 0:
        raise ValueError("embedding must be a non-empty 1D vector")
    return arr


def _decode_vector(blob: bytes | None) -> list[float]:
    if not blob:
        return []
    return np.frombuffer(blob, dtype=np.float32).astype(float).tolist()


def _decode_array(blob: bytes | None) -> Optional[np.ndarray]:
    if not blob:
        return None
    arr = np.frombuffer(blob, dtype=np.float32)
    if arr.size == 0:
        return None
    return arr

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Ensure every document's embedding is a flat, non-empty list/tuple of floats matching the collection dimension
  2. Skip or explicitly handle documents without embeddings rather than inserting empty lists
  3. Add a validation helper before insert: all(isinstance(e, (list, tuple)) and len(e) > 0 and not isinstance(e[0], list) for e in embeddings)
  4. Log the offending document id when validation fails to find the upstream embedder bug

Example fix

# before
col.add([{ "id": "d1", "text": "hello", "embedding": [] }])  # ValueError
# after
emb = embedder.encode("hello")
assert len(emb) == col.dimension
col.add([{ "id": "d1", "text": "hello", "embedding": emb }])
Defensive patterns

Strategy: validation

Validate before calling

def valid_embedding(e) -> bool:
    return (
        isinstance(e, (list, tuple))
        and len(e) > 0
        and all(isinstance(x, (int, float)) and not isinstance(x, bool) for x in e)
    )

docs = [d for d in docs if valid_embedding(d.get("embedding"))]  # or reject loudly

Type guard

def is_flat_nonempty_vector(v) -> bool:
    """True when v serializes to a non-empty 1D float32 vector."""
    return isinstance(v, (list, tuple)) and len(v) > 0 and all(
        isinstance(x, (int, float)) and not isinstance(x, bool) for x in v
    )

Try / catch

try:
    col.add(docs)
except ValueError as e:
    if "non-empty 1D" in str(e):
        bad = [d["id"] for d in docs if not is_flat_nonempty_vector(d.get("embedding"))]
        raise RuntimeError(f"invalid embeddings for ids: {bad}") from e
    raise

Prevention

When it happens

Trigger: add([{..., "embedding": []}]) (empty vector), embedding=[[0.1, 0.2]] (batch-shaped/nested), or embedding of a scalar. Also triggered when an embedder returns an empty vector for empty input and callers pass it through unvalidated.

Common situations: Embedder dimension/config mismatch producing empty outputs; code that batches documents and accidentally nests the embedding list; skipping an embedding step for some docs and storing an empty placeholder; None coerced to [None] then rejected by float32 conversion paths.

Related errors


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