agentscope-ai/agentscope · error · RuntimeError

Embedding model returned {len(response.embeddings)} vectors

Error message

Embedding model returned {len(response.embeddings)} vectors for {len(chunks)} chunks.

What it means

After embedding all chunk contents, the knowledge base verifies the embedding model returned exactly one vector per chunk. A count mismatch means the embedding provider returned fewer/more vectors (batching bug, provider inconsistency, or a custom embedding model with wrong return shape), so insertion aborts.

Source

Thrown at src/agentscope/rag/_knowledge.py:341

        document_id = document_id or _generate_id()

        await self.ensure_collection()

        # Precedence: metadata_filter wins (security boundary), then
        # chunk metadata, then document_metadata.  See docstring.
        for chunk in chunks:
            chunk.metadata = {
                **(document_metadata or {}),
                **chunk.metadata,
                **(self._metadata_filter or {}),
            }

        response = await self._embedding_model(
            [chunk.content for chunk in chunks],
        )

        if len(response.embeddings) != len(chunks):
            raise RuntimeError(
                f"Embedding model returned {len(response.embeddings)} "
                f"vectors for {len(chunks)} chunks.",
            )

        records = [
            VectorRecord(
                vector=vector,
                document_id=document_id,
                chunk=chunk,
            )
            for vector, chunk in zip(response.embeddings, chunks)
        ]
        await self._vector_store.insert(self._collection, records)
        return document_id

    async def delete_document(self, document_id: str) -> None:
        """Remove every record for one source document.

View on GitHub (pinned to e90f1c7592)

Solutions

  1. If using a custom embedding model, ensure it returns exactly one embedding per input, preserving order and count (pad/handle empty inputs rather than dropping them)
  2. Filter out empty/whitespace chunks before insert_document
  3. Reduce the batch/chunk count to isolate which inputs get dropped; log len(request) vs len(response.embeddings) in your wrapper
  4. Retry — some providers intermittently truncate; if persistent, switch embedding model

Example fix

# before (custom model drops empty inputs)
async def __call__(self, texts):
    texts = [t for t in texts if t]  # count mismatch!
    ...

# after
async def __call__(self, texts):
    texts = [t or ' ' for t in texts]  # keep 1:1 mapping
    ...
Defensive patterns

Strategy: validation

Validate before calling

chunks = [c for c in chunks if c.content and c.content.strip()]  # avoid empty inputs
await kb.insert_document(chunks)

Try / catch

try:
    await kb.insert_document(chunks)
except RuntimeError as e:
    if 'vectors for' not in str(e):
        raise
    # split into smaller batches and retry to isolate provider truncation

Prevention

When it happens

Trigger: Calling insert_document/build_index with a custom _embedding_model whose __call__ returns an EmbeddingResponse with truncated embeddings, or a provider that drops empty-text inputs from its response.

Common situations: Custom embedding wrappers that filter empty strings; provider batch-size limits silently truncating results; empty chunk content causing the provider to skip a vector; version changes in the embedding response format.

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/0ad1da0d640b4471. Report an issue: GitHub.