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
- 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)
- Filter out empty/whitespace chunks before insert_document
- Reduce the batch/chunk count to isolate which inputs get dropped; log len(request) vs len(response.embeddings) in your wrapper
- 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
- Custom embedding models must return exactly one vector per input in order
- Filter empty chunks before insertion
- Log input/output counts in embedding wrappers
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
- Path {path_file} exists but is not a file.
- "AgentScopeEmbedding requires `model` in the config to be an
- f"AgentScopeEmbedding `model` must be an EmbeddingModelBase,
- "AgentScope embedding model returned no embeddings."
- overlap must be less than chunk_size, got overlap={self.over
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/0ad1da0d640b4471.
Report an issue: GitHub.