MemPalace/mempalace · error · EmbeddingAPIError
Embedding API at {self._url} returned non-contiguous or dupl
Error message
Embedding API at {self._url} returned non-contiguous or duplicate 'index' values; cannot align embeddings with inputs What it means
Raised by _vectors_from_response when, after sorting rows by 'index', the resulting indices are not exactly 0..n-1. The check exists because servers may return rows out of order (sorted first) but must not use absolute offsets (e.g. 5,6,7 for a second batch), duplicates, or gaps — positional alignment between texts and vectors would silently misassign embeddings, violating the 100%-recall promise. Alignment must be provably correct, so any deviation is fatal.
Source
Thrown at mempalace/embedding.py:604
f"Embedding API at {self._url} returned no 'data' array: {data.get('error', data)}"
)
if len(rows) != n:
raise EmbeddingAPIError(
f"Embedding API at {self._url} returned {len(rows)} embeddings for {n} inputs"
)
# The endpoint may return rows out of order — sort by index, then
# 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()
View on GitHub (pinned to 06cb6987f0)
Solutions
- Curl with a 3-text batch and verify each row has index 0, 1, 2 exactly (0-based, per request)
- Fix stubs to include "index": i for every row
- If a gateway re-batches, point mempalace directly at the model server or fix the gateway to renumber indices per request
- Confirm no rows are dropped mid-pipeline (dropped rows create gaps that fail this check)
Example fix
# gateway pseudo-code — before
resp['data'] = all_rows # absolute indices from merged batch
# after
resp['data'] = [
{**row, 'index': i}
for i, row in enumerate(sorted(all_rows, key=lambda r: r['orig_pos']))
] Defensive patterns
Strategy: validation
Validate before calling
resp = probe(url, model, inputs=["a", "b"])
idx = sorted(r.get("index") for r in resp["data"])
assert idx == list(range(len(resp["data"]))), f"indices {idx} not 0-based contiguous" Type guard
def indices_are_contiguous(data) -> bool:
rows = data.get("data", [])
got = sorted(r.get("index", -1) for r in rows if isinstance(r, dict))
return got == list(range(len(rows))) Try / catch
try:
vecs = ef(texts)
except EmbeddingAPIError as e:
if "non-contiguous" in str(e):
log.error("server uses absolute/duplicate indices; fix gateway re-indexing")
raise Prevention
- Bypass aggregating proxies for the embeddings route, or make them renumber 0..n-1 per request
- Include an index-alignment assertion in your server's integration test
When it happens
Trigger: A server that echoes the global input index instead of per-request 0-based index (common when a proxy batches multiple clients); duplicate index values from a server bug; missing rows combined with extras (e.g. indices [0,0,2] for n=3); a stub that omits 'index' entirely so all rows default to -1 after sorting.
Common situations: Aggregating gateways that re-index across concatenated batches; stub servers omitting the index field; homegrown servers copying absolute IDs from their internal queue into 'index'.
Related errors
- 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}
- Embedding API at {self._url} returned malformed embeddings:
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/da2e90a78ca42a7e.
Report an issue: GitHub.