agentscope-ai/agentscope · error · ValueError
Cannot append DataBlock with URL source or different source
Error message
Cannot append DataBlock with URL source or different source types: {target_block.source} vs {chunk_block.source} What it means
ToolResponse.append_chunk refuses to merge DataBlocks when the existing target block and the incoming chunk block have incompatible sources (URL vs base64) or different source types; only same-type base64 merges are supported.
Source
Thrown at src/agentscope/tool/_response.py:114
if isinstance(
target_block.source,
Base64Source,
) and isinstance(chunk_block.source, Base64Source):
# Accumulate independently encoded base64 chunks.
target_block.source.data = _merge_base64_chunks(
target_block.source.data,
chunk_block.source.data,
)
# Update the newest media type and name if provided
target_block.name = (
chunk_block.name or target_block.name
)
target_block.source.media_type = (
chunk_block.source.media_type
or target_block.source.media_type
)
else:
raise ValueError(
"Cannot append DataBlock with URL source or "
f"different source types: {target_block.source} "
f"vs {chunk_block.source}",
)
else:
# For different block types with the same ID, we just
# append the new block with a new ID to avoid the conflict
new_chunk_block = chunk_block.model_copy(deep=True)
new_chunk_block.id = _generate_id()
self.content.append(new_chunk_block)
else:
# Append a copy to avoid modifying the original chunk
self.content.append(chunk_block.model_copy(deep=True))
# Update the index mapping for the new block
current_ids_to_index[chunk_block.id] = len(self.content) - 1
View on GitHub (pinned to e90f1c7592)
Solutions
- Fix the server to use a consistent source type for a given block id
- Start a new block (different id) when switching from URL to inline data
- Catch ValueError in append_chunk and keep blocks separate instead of merging
Example fix
# before
resp.append_chunk(chunk) # url block + base64 chunk, same id
# after
if target_block.source.type != chunk_block.source.type:
chunk_block.id = new_id # keep as separate block
resp.append_chunk(chunk) Defensive patterns
Strategy: type-guard
Validate before calling
same_type = target.source.type == chunk.source.type and target.source.type == 'base64'
Type guard
def can_append(target_block, chunk_block) -> bool:
return target_block.source.type == chunk_block.source.type == 'base64' Try / catch
try:
resp.append_chunk(chunk)
except ValueError as e:
if 'different source types' in str(e):
chunk.id = fresh_id
raise Prevention
- Use one transfer mode (URL or base64) per block id
- Re-id blocks when switching source types
- Test streaming tool responses against the aggregator
When it happens
Trigger: Streaming a tool response where the same block id first carries a URL source then a base64 chunk (or vice versa), causing append_chunk to hit the mismatch branch. Reached via call_tool chunk aggregation.
Common situations: MCP servers switching transfer modes mid-stream, or a server that sends the first chunk as a URL reference and later chunks as inline base64 with the same block id.
Related errors
- STDIO MCP does not support ephemeral mode. Use 'shared' or '
- Invalid values for MCP {card.name!r}: {e.message}
- MCP {card.name!r} needs a value for: {', '.join(sorted(missi
- MCP {card.name!r} produced an invalid client: {e}
- {entry.path!r} is larger than its declared {entry.size} byte
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/2c1cf8489471b2c7.
Report an issue: GitHub.