{"record":{"id":"8377c8622cd70ce7","repo":"run-llama/llama_index","slug":"no-embeddings-to-aggregate","errorCode":null,"errorMessage":"No embeddings to aggregate","messagePattern":"No embeddings to aggregate","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/base/embeddings/base.py","lineNumber":50,"sourceCode":"    EmbeddingStartEvent,\n)\nimport llama_index.core.instrumentation as instrument\n\ndispatcher = instrument.get_dispatcher(__name__)\n\n\nclass SimilarityMode(str, Enum):\n    \"\"\"Modes for similarity/distance.\"\"\"\n\n    DEFAULT = \"cosine\"\n    DOT_PRODUCT = \"dot_product\"\n    EUCLIDEAN = \"euclidean\"\n\n\ndef mean_agg(embeddings: List[Embedding]) -> Embedding:\n    \"\"\"Mean aggregation for embeddings.\"\"\"\n    if not embeddings:\n        raise ValueError(\"No embeddings to aggregate\")\n\n    return np.array(embeddings).mean(axis=0).tolist()\n\n\ndef similarity(\n    embedding1: Embedding,\n    embedding2: Embedding,\n    mode: SimilarityMode = SimilarityMode.DEFAULT,\n) -> float:\n    \"\"\"Get embedding similarity.\"\"\"\n    if mode == SimilarityMode.EUCLIDEAN:\n        # Using -euclidean distance as similarity to achieve same ranking order\n        return -float(np.linalg.norm(np.array(embedding1) - np.array(embedding2)))\n    elif mode == SimilarityMode.DOT_PRODUCT:\n        return np.dot(embedding1, embedding2)\n    else:\n        product = np.dot(embedding1, embedding2)\n        norm = np.linalg.norm(embedding1) * np.linalg.norm(embedding2)","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/base/embeddings/base.py#L32-L68","documentation":"Raised by mean_agg when it is called with an empty list of embeddings. Mean aggregation over zero vectors is undefined, so the function fails fast instead of returning NaN or a zero vector. This helper backs similarity averaging in BaseEmbedding.","triggerScenarios":"Aggregating embeddings for a node whose text is empty, or calling get_text_embedding over a chunk list that filtered down to zero items before aggregation; passing [] to mean_agg directly.","commonSituations":"Indexing documents that produce empty text nodes (blank pages, whitespace-only extraction); pipelines that batch texts and pass an exhausted/filtered batch; splitting logic yielding zero chunks for a document.","solutions":["Skip aggregation when the embedding list is empty: `if embeddings: ... else: continue`.","Fix upstream node construction so empty-text nodes are dropped (e.g. filter nodes with not node.get_content().strip()).","If an empty aggregate must exist for your schema, decide an explicit policy (skip node, or raise a clearer domain error) rather than relying on this generic one."],"exampleFix":"# before\nemb = mean_agg(get_text_embeddings_for_node_batch(node_batch))\n\n# after\nembs = get_text_embeddings_for_node_batch(node_batch)\nif embs:\n    emb = mean_agg(embs)\nelse:\n    node_batch = [n for n in node_batch if n.get_content().strip()]","handlingStrategy":"validation","validationCode":"texts = [t for t in texts if t and t.strip()]\nif not texts:\n    return  # nothing to aggregate","typeGuard":"def has_embeddings(embs: list) -> bool:\n    return len(embs) > 0","tryCatchPattern":"try:\n    agg = mean_agg(embs)\nexcept ValueError:\n    logger.warning(\"empty embedding batch, skipping node\")","preventionTips":["Filter empty/whitespace text before embedding.","Drop empty nodes at node-parser time rather than at aggregation time."],"tags":["llama-index","embeddings","empty-input","aggregation"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}