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 resolved

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Confirm the server honors encoding_format='float' in the request and returns plain float arrays in each row's 'embedding' field
  2. Update the embedding server to a version that respects the OpenAI encoding_format parameter, or disable its base64 default
  3. Verify all vectors share the same dimensionality as the model's output
  4. 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

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

Related errors


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