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

  1. Fix the server to use a consistent source type for a given block id
  2. Start a new block (different id) when switching from URL to inline data
  3. 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

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


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