{"record":{"id":"8d5b184e88f8d095","repo":"MemPalace/mempalace","slug":"embedding-must-be-a-non-empty-1d-vector-8d5b18","errorCode":null,"errorMessage":"embedding must be a non-empty 1D vector","messagePattern":"embedding must be a non-empty 1D vector","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/qdrant.py","lineNumber":239,"sourceCode":"    *,\n    documents: list[str],\n    ids: list[str],\n    metadatas: Optional[list[dict]],\n    embeddings: Optional[list[list[float]]],\n) -> None:\n    n = len(ids)\n    if len(documents) != n:\n        raise ValueError(f\"documents length {len(documents)} does not match ids length {n}\")\n    if metadatas is not None and len(metadatas) != n:\n        raise ValueError(f\"metadatas length {len(metadatas)} does not match ids length {n}\")\n    if embeddings is not None and len(embeddings) != n:\n        raise ValueError(f\"embeddings length {len(embeddings)} does not match ids length {n}\")\n\n\ndef _as_vector_array(vector: list[float]) -> np.ndarray:\n    arr = np.asarray(vector, dtype=np.float32)\n    if arr.ndim != 1 or arr.size == 0:\n        raise ValueError(\"embedding must be a non-empty 1D vector\")\n    return arr\n\n\ndef _normalize_vectors(embeddings: list[list[float]]) -> tuple[list[list[float]], int]:\n    vectors = []\n    dims = set()\n    for embedding in embeddings:\n        arr = _as_vector_array(embedding)\n        vectors.append(arr.astype(float).tolist())\n        dims.add(int(arr.size))\n    if len(dims) > 1:\n        raise DimensionMismatchError(f\"qdrant batch cannot mix embedding dimensions {sorted(dims)}\")\n    return vectors, dims.pop() if dims else 0\n\n\ndef _jsonable_metadata(meta: dict | None) -> dict:\n    try:\n        value = json.loads(json.dumps(meta or {}, ensure_ascii=False))","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/qdrant.py#L221-L257","documentation":"Raised by _as_vector_array() when an individual embedding passed to the Qdrant backend is not a non-empty 1D sequence of numbers. The helper converts the input to a float32 numpy array and requires arr.ndim == 1 and arr.size > 0. This is a fail-fast guard so malformed vectors never reach the remote Qdrant server.","triggerScenarios":"Calling collection.upsert()/add() with an embedding that is an empty list [], a scalar (e.g. 0.5), a nested list ([[1,2],[3,4]] as a single embedding), or a ragged/nested structure that numpy flattens to ndim != 1. Also triggered via _normalize_vectors() during upsert, or during query() when a query_vector inside query_embeddings is empty/scalar.","commonSituations":"The embedding model returned an empty vector (Ollama/LM Studio returned no embedding for an empty string), a caller passed a batch where one row is [], or a dimension mismatch caused nesting like [[...],[...]] being treated as one vector. Also when text is empty and the embedder silently yields empty output.","solutions":["Log and inspect the failing embedding: check len() and shape of each vector before submit; find which row is empty or nested","Ensure the embedder call skips or rejects empty input text rather than returning an empty list","If batching, validate embeddings with a helper (all(isinstance(v, (list, tuple)) and len(v) > 0 for v in embeddings)) before calling upsert/add","If the model genuinely returns 0-dim for some input, filter those rows out or raise a clearer upstream error in your pipeline"],"exampleFix":"// before\n collection.upsert(documents=docs, ids=ids, embeddings=[model.embed(d) for d in docs])  # one embedding empty\n// after\n embeddings = [model.embed(d) for d in docs]\n if any(not isinstance(v, (list, tuple)) or len(v) == 0 for v in embeddings):\n     raise ValueError(\"embedder returned an empty/invalid vector\")\n collection.upsert(documents=docs, ids=ids, embeddings=embeddings)","handlingStrategy":"validation","validationCode":"def valid_embeddings(embeddings):\n    return all(\n        isinstance(e, (list, tuple)) and len(e) > 0 and all(isinstance(x, (int, float)) for x in e)\n        for e in embeddings\n    )\n\nif not valid_embeddings(embeddings):\n    raise ValueError(\"bad embeddings batch\")","typeGuard":"def is_embedding_list(v) -> bool:\n    return isinstance(v, list) and bool(v) and all(\n        isinstance(e, list) and len(e) > 0 and all(isinstance(x, (int, float)) for x in e)\n        for e in v\n    )","tryCatchPattern":null,"preventionTips":["Validate embedder output length once at startup: assert len(embed('test')) > 0","Never feed empty strings to the embedder without handling the empty result","Log {len(e) for e in embeddings} in debug builds to catch nesting/empty vectors early"],"tags":["validation","embeddings","qdrant","numpy"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}