MemPalace/mempalace · error · EmbeddingAPIError
Embedding API at {self._url} returned malformed embeddings:
Error message
Embedding API at {self._url} returned malformed embeddings: {e} What it means
Raised by _vectors_from_response when building np.asarray([r['embedding'] for r in rows], dtype=np.float32) fails with KeyError (a row missing the 'embedding' key), TypeError (embedding present but not array-like, e.g. a dict), or ValueError (strings or ragged lists that cannot become a uniform float32 array). This blocks non-numeric or ragged payloads — including base64-encoded embeddings — before they can corrupt the vector store.
Source
Thrown at mempalace/embedding.py:611
# require the indices to be exactly 0..n-1 so positional alignment is
# provably correct (a server using absolute or duplicate indices would
# otherwise pass the count check yet map vectors to the wrong texts).
try:
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 resolvedView on GitHub (pinned to 06cb6987f0)
Solutions
- Confirm the server honors encoding_format='float' in the request and returns plain float arrays in each row's 'embedding' field
- Update the embedding server to a version that respects the OpenAI encoding_format parameter, or disable its base64 default
- Verify all vectors share the same dimensionality as the model's output
- Curl one request and inspect the raw JSON of a single data row
Example fix
# server — before
e = base64.b64encode(vec.astype(np.float32).tobytes()).decode()
return {"data": [{"index": i, "embedding": e}]}
# after
return {"data": [{"index": i, "embedding": vec.tolist()}]} Defensive patterns
Strategy: validation
Validate before calling
import base64 row = resp["data"][0]["embedding"] assert not isinstance(row, str), "server returned base64 despite encoding_format=float" assert all(isinstance(v, (int, float)) for v in row), "non-numeric embedding values"
Type guard
def embeddings_are_numeric(data) -> bool:
try:
rows = data["data"]
return all(isinstance(r["embedding"], list)
and all(isinstance(v, (int, float)) for v in r["embedding"])
for r in rows)
except (KeyError, TypeError):
return False Try / catch
try:
vecs = ef(texts)
except EmbeddingAPIError as e:
if "malformed embeddings" in str(e):
log.error("server ignored encoding_format=float (likely base64); fix server or upgrade it")
raise Prevention
- Use a server version that honors the encoding_format parameter
- Check one raw response with curl before wiring a new embedding backend
- Keep embedding dimensionality constant across your deployment
When it happens
Trigger: A server returns embeddings as base64 strings (the exact case the caller's encoding_format='float' request was meant to prevent); a row omits 'embedding'; vectors of differing lengths across rows (ragged); embedding values as strings ('0.14').
Common situations: A server that ignores encoding_format and defaults to base64; older servers returning 'embedding' under a different key ('vector', 'values'); quantized servers returning mixed-dimension rows; middleware converting numbers to strings.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Embedding API at {self._url} returned non-vector 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/ae5a6afb32dc1f55.
Report an issue: GitHub.