TypeError in streamed tool-call reconstruction when decoded function arguments are null
>>> [!note] Migrated issue <!-- Drupal.org comment --> <!-- Migrated from issue #3582345. --> Reported by: [merilainen](https://www.drupal.org/user/304437) Related to !1377 >>> <p>[Tracker]<br> <strong>Update Summary: </strong>Patched streamed tool-call reconstruction to handle null/invalid decoded arguments and prevent a fatal TypeError.<br> <strong>Short Description: </strong>Streamed tool-call handling can pass null arguments to ToolsFunctionOutput, causing a TypeError during chat stream reconstruction.<br> <strong>Check-in Date: </strong>03/31/2026<br> <em>Metadata is used by the <a href="https://www.drupalstarforge.ai/" title="AI Tracker">AI Tracker.</a> Docs and additional fields <a href="https://www.drupalstarforge.ai/ai-dashboard/docs" title="AI Issue Tracker Documentation">here</a>.</em><br> [/Tracker]</p> <h3 id="summary-problem-motivation">Problem/Motivation</h3> <p>When AI tool calls are reconstructed from streamed chunks, function arguments are JSON-decoded from partial/aggregated stream data. In some cases, decoding returns null (for example empty/incomplete/non-object JSON).<br> The streamed assembler then passes that null value into ToolsFunctionOutput::__construct(), where argument #3 is typed as array, triggering a fatal TypeError and breaking agent workflows.</p> <p>Observed error:</p> <p>TypeError: Drupal\ai\OperationType\Chat\Tools\ToolsFunctionOutput::__construct(): Argument #3 ($arguments) must be of type array, null given, called in /var/www/html/web/modules/contrib/ai/src/OperationType/Chat/StreamedChatMessageIterator.php on line 540 in Drupal\ai\OperationType\Chat\Tools\ToolsFunctionOutput-&gt;__construct() (line 45 of /var/www/html/web/modules/contrib/ai/src/OperationType/Chat/Tools/ToolsFunctionOutput.php).</p> <h4 id="summary-steps-reproduce">Steps to reproduce (required for bugs, but not feature requests)</h4> <p>Please provide information like AI modules enabled, which AI provider, browser, etc.</p> <p>1. Enable AI module with tool-calling enabled and use any provider that supports streamed tool call chunks.<br> 2. Run an agent/tool-call scenario where tool-call arguments are streamed in partial chunks (or malformed/empty at intermediate stages).<br> 3. Let the stream complete so StreamedChatMessageIterator::assembleToolCalls() reconstructs tool calls.<br> 4. In affected cases, Json::decode(...) for arguments returns null.<br> 5. Stream reconstruction creates ToolsFunctionOutput with null as $arguments, causing a TypeError and aborting the response.</p> <p>Environment details to include when reproducing:<br> - Drupal core: 11.3.5<br> - AI module version: 1.3.0<br> - AI provider and model: GPT 5.2<br> - Was using agent explorer</p> <h3 id="summary-proposed-resolution">Proposed resolution</h3> <p>Harden streamed tool-call reconstruction in StreamedChatMessageIterator::assembleToolCalls():</p> <p>- Decode arguments with a safe fallback input: arguments ?? '{}'<br> - Normalize decoded value:<br> - If decoded result is an array, use it<br> - Otherwise, use an empty array []<br> - Apply this in both reconstruction points:<br> - When flushing previous tool call on new tool id<br> - When finalizing the last accumulated tool call</p> <p>This ensures ToolsFunctionOutput always receives an array and prevents fatal errors from transient/invalid streamed argument payloads.</p> <h3>Optional: Other details as applicable (e.g., User interface changes, API changes, Data model changes)</h3> <p>- User interface changes: None.<br> - API changes: None (internal robustness fix only).<br> - Data model changes: None.<br> - Backward compatibility: Preserved.</p> <h3 id="summary-ai-usage">AI usage (if applicable)</h3> <p>[x] AI Assisted Issue<br> This issue was generated with AI assistance, but was reviewed and refined by the creator.</p> <p>[x] AI Generated Code<br> This code was mainly generated by an AI with human guidance, and reviewed, tested, and refined by a human.</p>
issue