agentscope-ai/agentscope · error · ValueError

User message can only contain text blocks or data blocks.

Error message

User message can only contain text blocks or data blocks.

What it means

Msg content validation restricts user-role messages to TextBlock and data blocks only; images, audio, video, tool-use blocks, or any other block type in a user message raise this ValueError. This enforces the role/block-type contract used by formatters and models.

Source

Thrown at src/agentscope/message/_base.py:37

    ToolResultBlock,
    ToolResultState,
    ContentBlock,
    ContentBlockTypes,
)
from ..types import ReplyFinishedReason, ErrorInfo
from .._logging import logger

if TYPE_CHECKING:
    from ..event import AgentEvent
else:
    AgentEvent = Any


def _assert_user_content_blocks(content: Sequence[ContentBlock]) -> None:
    """Assert that the content blocks in user message are valid."""
    for block in content:
        if block.type not in ["text", "data"]:
            raise ValueError(
                "User message can only contain text blocks or data blocks.",
            )


def _assert_system_content_blocks(
    content: Sequence[ContentBlock],
) -> None:
    """Assert that the content blocks in system message are valid."""
    for block in content:
        if block.type not in ["text"]:
            raise ValueError("System message can only contain text blocks.")


def _to_blocks(content: str | list) -> list:
    """Convert a plain string to a single-element TextBlock list."""
    if isinstance(content, str):
        return [TextBlock(text=content)]
    return content

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Remove non-text/data blocks from user content; move images/media into a tool result or the block type the target model API prescribes for user media
  2. Check the block's .type values before constructing the Msg (see validation code)
  3. Upgrade/check docs: newer agentscope versions may prescribe a specific multimodal user-message pattern

Example fix

// before
msg = Msg("user", content=[TextBlock(type="text", text="what is this?"), ImageBlock(type="image", ...)], role="user")

// after
msg = Msg("user", content=[TextBlock(type="text", text="what is this?")], role="user")
# attach media through the supported channel, e.g. a multimodal/tool-result block per docs
Defensive patterns

Strategy: type-guard

Validate before calling

allowed = {"text", "data"}
assert all(b.type in allowed for b in user_blocks), f"bad user block: {[b.type for b in user_blocks]}"

Type guard

def is_valid_user_content(blocks) -> bool:
    return all(b.type in ("text", "data") for b in blocks)

Try / catch

try:
    Msg("user", role="user", content=blocks)
except ValueError as e:
    if "text blocks or data blocks" in str(e):
        blocks = [b for b in blocks if b.type in ("text", "data")]

Prevention

When it happens

Trigger: Msg("user", role="user", content=[TextBlock(...), ImageBlock(...)]) — any block whose type is not "text" or "data" inside a user message; also converting third-party message payloads (e.g. multimodal OpenAI content) to Msg without filtering.

Common situations: Trying to send an image directly in a user message instead of via the API's expected mechanism (e.g. a dedicated multimodal message type or tool result); assembling messages programmatically without role-specific validation; porting chat histories from other frameworks.

Related errors


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