run-llama/llama_index · error · ValueError

CitableBlock content must contain exactly one block when pro

Error message

CitableBlock content must contain exactly one block when provided as a list.

What it means

Raised by CitableBlock's cited_content field validator when cited_content is supplied as a list whose length is not exactly 1. The model accepts a plain str, a single block, or a one-element list (whose element may be a str); multiple blocks are ambiguous for a citation and rejected.

Source

Thrown at llama-index-core/llama_index/core/base/llms/types.py:1066

class CitationBlock(BaseRecursiveContentBlock):
    """A representation of cited content from past messages."""

    block_type: Literal["citation"] = "citation"
    cited_content: Annotated[
        Union[TextBlock, ImageBlock], Field(discriminator="block_type")
    ]
    source: str
    title: str
    additional_location_info: Dict[str, int]

    @field_validator("cited_content", mode="before")
    @classmethod
    def validate_cited_content(cls, v: Any) -> Any:
        if isinstance(v, str):
            return TextBlock(text=v)
        if isinstance(v, list):
            if len(v) != 1:
                raise ValueError(
                    "CitableBlock content must contain exactly one block when provided as a list."
                )
            value = v[0]
            if isinstance(value, str):
                return TextBlock(text=value)
            else:
                return value
        return v

    @classmethod
    def nested_blocks_field_name(self) -> str:
        return "cited_content"

    def can_merge(self, other: Self) -> bool:
        """Check if this block can be merged with another block of the same type."""
        # Only merge if cited_content is of the same type and is a TextBlock
        if type(self.cited_content) is type(other.cited_content) and isinstance(
            self.cited_content, TextBlock

View on GitHub (pinned to afd0fef371)

Solutions

  1. Create one CitableBlock per cited passage instead of one with many blocks.
  2. If a list is used, ensure it has exactly one element (str or block).
  3. Pass a plain string when the citation is simple text: cited_content="...".

Example fix

# before
cited = CitableBlock(cited_content=[TextBlock(text=p1), TextBlock(text=p2)], source=..., title=..., additional_location_info={})

# after
cited = [
    CitableBlock(cited_content=TextBlock(text=p1), source=..., title=..., additional_location_info={}),
    CitableBlock(cited_content=TextBlock(text=p2), source=..., title=..., additional_location_info={}),
]
Defensive patterns

Strategy: validation

Validate before calling

if isinstance(cited_content, list) and len(cited_content) != 1:
    blocks = [CitableBlock(cited_content=c, source=s, title=t, additional_location_info=i) for c in cited_content]

Type guard

def is_valid_cited_content(v: Any) -> bool:
    return isinstance(v, str) or (isinstance(v, list) and len(v) == 1)

Prevention

When it happens

Trigger: Constructing CitableBlock(cited_content=[TextBlock(...), TextBlock(...)]) (2+ items) or cited_content=[] (empty list); building citation objects from search hits without limiting to one block.

Common situations: Programmatically collecting multiple retrieved passages into one citation instead of creating one CitableBlock per passage; passing an empty list from a failed retrieval step.

Related errors


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/395382817bfbbf41. Report an issue: GitHub.