{"record":{"id":"64981f8780914134","repo":"run-llama/llama_index","slug":"cannot-provide-both-content-and-blocks","errorCode":null,"errorMessage":"Cannot provide both content and blocks.","messagePattern":"Cannot provide both content and blocks\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/tools/types.py","lineNumber":128,"sourceCode":"    tool_name: str\n    raw_input: Dict[str, Any]\n    raw_output: Any\n    is_error: bool = False\n\n    _exception: Optional[Exception] = PrivateAttr(default=None)\n\n    def __init__(\n        self,\n        tool_name: str,\n        content: Optional[str] = None,\n        blocks: Optional[List[ContentBlock]] = None,\n        raw_input: Optional[Dict[str, Any]] = None,\n        raw_output: Optional[Any] = None,\n        is_error: bool = False,\n        exception: Optional[Exception] = None,\n    ):\n        if content and blocks:\n            raise ValueError(\"Cannot provide both content and blocks.\")\n        if content:\n            blocks = [TextBlock(text=content)]\n        elif blocks:\n            pass\n        else:\n            blocks = []\n\n        super().__init__(\n            tool_name=tool_name,\n            blocks=blocks,\n            raw_input=raw_input,\n            raw_output=raw_output,\n            is_error=is_error,\n        )\n\n        self._exception = exception\n\n    @property","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/tools/types.py#L110-L146","documentation":"ToolOutput.__init__ accepts either a plain string content or a list of ContentBlock objects (blocks), but not both. Passing a truthy content AND a non-empty blocks list raises ValueError because the two representations would conflict; internally content is just converted to [TextBlock(text=content)].","triggerScenarios":"Constructing ToolOutput(tool_name='x', content='result text', blocks=[TextBlock(text='result text')]) or subclassing ToolOutput and forwarding both parameters. Also hit by wrapper code that adds a default content string while passing through caller-supplied blocks.","commonSituations":"Custom tool implementations building rich (multi-block) outputs while keeping a legacy content argument 'just in case'; refactors from string outputs to block outputs that forget to remove the old content kwarg.","solutions":["Pass only one form: either content='text' or blocks=[TextBlock(...), ImageBlock(...)].","If you need a text summary plus blocks, embed it as a TextBlock inside blocks.","In wrapper/generic code, choose blocks when the caller supplied blocks, else content."],"exampleFix":"# before\n out = ToolOutput(\n     tool_name='search',\n     content='hello',\n     blocks=[TextBlock(text='hello')],  # both supplied -> ValueError\n )\n\n# after\n out = ToolOutput(tool_name='search', blocks=[TextBlock(text='hello')])","handlingStrategy":"validation","validationCode":"def build_tool_output(tool_name: str, content=None, blocks=None):\n    if content and blocks:\n        raise TypeError('Pass content OR blocks, not both')\n    if content:\n        return ToolOutput(tool_name=tool_name, content=content)\n    return ToolOutput(tool_name=tool_name, blocks=blocks or [])","typeGuard":"def has_conflicting_output_args(content, blocks) -> bool:\n    return bool(content) and bool(blocks)","tryCatchPattern":"try:\n    out = ToolOutput(tool_name=name, content=c, blocks=b)\nexcept ValueError as e:\n    if 'both content and blocks' in str(e) and b:\n        out = ToolOutput(tool_name=name, blocks=b)  # blocks win\n    else:\n        raise","preventionTips":["Pick one output form per code path; never forward both kwargs in wrappers.","Convert legacy strings to [TextBlock(text=...)] when migrating to blocks.","Centralize ToolOutput construction in one helper that enforces the rule."],"tags":["tool-output","content-blocks","validation","value-error"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}