agentscope-ai/agentscope · error · ValueError
Invalid input: {item!r}. Expected str or DataBlock.
Error message
Invalid input: {item!r}. Expected str or DataBlock. What it means
The Gemini multimodal embedding path only accepts two input shapes per item: plain str (text) or a DataBlock instance (image/audio/video). Anything else (dict, bytes, int, PIL image, None) fails validation before the request is built.
Source
Thrown at src/agentscope/embedding/_gemini/_model.py:416
"""
from google.genai import types
contents: list[types.Content] = []
for item in inputs:
if isinstance(item, str):
contents.append(
types.Content(
parts=[types.Part.from_text(text=item)],
),
)
elif isinstance(item, DataBlock):
contents.append(
types.Content(
parts=[self._data_block_to_part(item)],
),
)
else:
raise ValueError(
f"Invalid input: {item!r}. Expected str or DataBlock.",
)
config = types.EmbedContentConfig(
output_dimensionality=self.dimensions,
**kwargs,
)
start_time = datetime.now()
response = self.client.models.embed_content(
model=self.model,
contents=contents,
config=config,
)
time = (datetime.now() - start_time).total_seconds()
embeddings = [item.values for item in response.embeddings]
View on GitHub (pinned to e90f1c7592)
Solutions
- Wrap binary/structured items in DataBlock with a proper source (Base64Source for inline data)
- Convert PIL images to PNG bytes and wrap in DataBlock with Base64Source and media_type
- Keep plain strings as-is for text parts of the batch
Example fix
# before
emb = await model(inputs=[{"type": "image", "data": png_bytes}])
# after
from agentscope.message import DataBlock, Base64Source
block = DataBlock(source=Base64Source(data=png_bytes, media_type="image/png"))
emb = await model(inputs=["describe", block]) Defensive patterns
Strategy: type-guard
Validate before calling
from agentscope.message import DataBlock ok = all(isinstance(x, (str, DataBlock)) for x in inputs)
Type guard
from agentscope.message import DataBlock
from typing import Union
def is_valid_multimodal_input(inputs: list) -> bool:
return all(isinstance(x, (str, DataBlock)) for x in inputs) Try / catch
try:
emb = await model(inputs=inputs)
except ValueError as e:
if "Expected str or DataBlock" in str(e):
inputs = [x if isinstance(x, (str, DataBlock)) else to_data_block(x) for x in inputs]
emb = await model(inputs=inputs)
else:
raise Prevention
- Always wrap media in DataBlock with a proper source
- Write a to_data_block(obj) adapter for your raw types
- Reject dict-shaped OpenAI-style items before calling the model
When it happens
Trigger: Calling the multimodal embedding model with items like {"type": "image_url", ...} raw dicts, raw bytes, or PIL Image objects instead of DataBlock wrappers; routed through _call_api -> _call_multimodal.
Common situations: Porting code from OpenAI-style embedding APIs that take dicts; assuming bytes or PIL images are accepted; older examples passing tuples of (data, mime_type).
Related errors
- Text embedding model {self.model!r} only accepts str inputs,
- Gemini embedding API requires inline data (Base64Source). UR
- Unsupported source type {type(source).__name__} in DataBlock
- Invalid input: {item!r}. Expected str or DataBlock.
- DashScope multimodal embedding API error: {res}
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/5904b4328714b07d.
Report an issue: GitHub.