MemPalace/mempalace · error · EmbeddingAPIError
Embedding API at {self._url} returned non-vector embeddings
Error message
Embedding API at {self._url} returned non-vector embeddings (shape {arr.shape}) What it means
Raised by _vectors_from_response when the assembled float32 array is not 2-dimensional (arr.ndim != 2). After the row checks pass, this catches payloads where per-row 'embedding' values collapse into a scalar or inflate into extra dimensions (e.g. every value is itself a nested list), which the shape in the message reveals. Vectors must be a clean (n, dim) matrix before L2 normalization, or the cosine-space store would receive garbage.
Source
Thrown at mempalace/embedding.py:615
rows = sorted(rows, key=lambda d: d.get("index", -1))
indices = [r.get("index") for r in rows]
except AttributeError as e:
raise EmbeddingAPIError(
f"Embedding API at {self._url} returned non-object rows: {e}"
) from e
if indices != list(range(n)):
raise EmbeddingAPIError(
f"Embedding API at {self._url} returned non-contiguous or duplicate "
f"'index' values; cannot align embeddings with inputs"
)
try:
arr = np.asarray([r["embedding"] for r in rows], dtype=np.float32)
except (KeyError, TypeError, ValueError) as e:
raise EmbeddingAPIError(
f"Embedding API at {self._url} returned malformed embeddings: {e}"
) from e
if arr.ndim != 2:
raise EmbeddingAPIError(
f"Embedding API at {self._url} returned non-vector embeddings (shape {arr.shape})"
)
# L2-normalize so cosine == dot product (collection uses
# hnsw:space=cosine), matching EmbeddinggemmaONNX above.
norms = np.linalg.norm(arr, axis=1, keepdims=True) + 1e-12
return (arr / norms).tolist()
def get_embedding_function(device: Optional[str] = None, model: Optional[str] = None):
"""Return a cached embedding function for the requested device + model.
``device=None`` reads :attr:`MempalaceConfig.embedding_device`;
``model=None`` reads :attr:`MempalaceConfig.embedding_model`.
The returned function is shared across calls with the same resolved
provider list + model so we only pay model-load cost once per process.
"""
if device is None or model is None:
from .config import MempalaceConfigView on GitHub (pinned to 06cb6987f0)
Solutions
- Read the reported shape: (n,) => scalars, add a dimension server-side; (n, k, d) => extra nesting, flatten one level
- Fix the server to return exactly a flat list of floats per row: "embedding": [f1, f2, ..., fd]
- Validate with curl that one row's embedding is a flat numeric JSON array
- Confirm the model actually produces dense vectors (a reranker/score endpoint does not)
Example fix
# stub — before
return {"data": [{"index": 0, "embedding": score}]} # scalar
# or
return {"data": [{"index": 0, "embedding": [vec]}]} # nested
# after
return {"data": [{"index": 0, "embedding": vec.tolist()}]} # flat floats Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
arr = np.asarray([r["embedding"] for r in resp["data"]], dtype=np.float32)
assert arr.ndim == 2, f"expected 2-D (n, dim), got shape {arr.shape}" Type guard
def embeddings_form_matrix(data) -> bool:
try:
arr = np.asarray([r["embedding"] for r in data["data"]], dtype=np.float32)
return arr.ndim == 2 and arr.shape[1] > 0
except (KeyError, TypeError, ValueError):
return False Try / catch
try:
vecs = ef(texts)
except EmbeddingAPIError as e:
if "non-vector embeddings" in str(e):
log.error("shape %s — server emits scalars or nested vectors", e) # read shape from message
raise Prevention
- Do not point mempalace at score/rerank endpoints — they return scalars, not vectors
- Stub servers must return a flat float list per text
When it happens
Trigger: All rows have scalar embeddings ("embedding": 0.5), each 'embedding' is a nested list ([[...]]) producing ndim=3, or an empty-batch edge where the array degenerates. Shape in the message distinguishes these: (3,) means scalars; (3, 2, 768) means doubly-nested.
Common situations: Stub servers returning a single float per text; servers wrapping the vector in an extra list level; quantized endpoints returning per-value objects; JSON middleware that transforms arrays.
Related errors
- Embedding API at {self._url} returned malformed embeddings:
- Embedding API at {self._url} returned a non-object response:
- Embedding API at {self._url} returned no 'data' array: {data
- Embedding API at {self._url} returned {len(rows)} embeddings
- Embedding API at {self._url} returned non-object rows: {e}
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/7eabafee9bf80e81.
Report an issue: GitHub.