Problem/Motivation

The ai_agents_views:update_view_plugins tool (UpdateViewPlugins::execute()) can crash the entire AI agent process, not just the one tool call, when given a wrong-but-plausible display ID.

execute() calls ViewsAgentHelper::getViewDisplayOptionsConfig() twice: once (already guarded by a try/catch) when config is missing, to list the available values, and a second time - completely unguarded - once display_id, display_option, and config are all provided, right before actually applying the change. If the display ID is wrong at that point (for example, an LLM guessing page instead of the real page_1), getViewDisplayOptionsConfig() throws a plain \Exception, and this second call site lets it escape execute() uncaught.

This tool runs with catch_errors disabled, so an uncaught exception doesn't become a normal tool-call failure the calling agent can read and recover from - it terminates the whole agent run. In an interactive session (ddev drush agent views_agent), this ends the process outright; in any automated or unattended use of the agent, it means one wrong display ID guess kills the entire task instead of prompting the agent to retry with the correct ID.

Steps to reproduce

  1. Create or load a View with at least one non-default display, e.g. page_1.
  2. Call ai_agents_views:update_view_plugins with every argument provided but a wrong, plausible-looking display ID:
    • id: the view's machine name
    • display_id: page (wrong - the real display is page_1)
    • display_option: any valid option, e.g. use_ajax
    • config: any valid value, e.g. true

Expected: a normal tool result explaining the display ID doesn't exist, so the calling agent can retry.

Actual: an uncaught \Exception escapes execute() and terminates the agent process.

Root cause

Three early-return branches in execute() already guard their own call to getViewDisplayOptionsConfig() with try/catch, for the cases where display_id, display_option, or config is missing. But once all three are present, the code calls the same method again, unguarded, to fetch the option's current/available values before applying the write:

$default_config = $this->viewsAgentHelper->getViewDisplayOptionsConfig($id, $display_id, $display_option);

// Decode the config JSON string.
$config_decoded = Json::decode($config);
...

getViewDisplayOptionsConfig() throws a plain \Exception ("The Display ID '...' does not exist on '...'.") when the display ID isn't real. With no try/catch at this call site, and catch_errors disabled for this tool, that exception is never turned into a tool result - it propagates all the way out and kills the process.

Proposed resolution

Wrap the second call site in the same try/catch pattern already used by the other three:

try {
  $default_config = $this->viewsAgentHelper->getViewDisplayOptionsConfig($id, $display_id, $display_option);
}
catch (\Exception $e) {
  $this->list = $e->getMessage();
  return;
}

Also adds a "Display IDs" section to the shipped system prompt, so the model is told not to guess a display ID and how to recover (re-list displays, retry) when a tool call reports one doesn't exist. Tested this prompt-only mitigation alone first, on the live agent - it did not change the crash behavior on its own, confirming this needs the code fix, not just prompt wording.

Remaining tasks

  • File this issue on drupal.org.
  • Open an MR with the fix above.

Test coverage added locally

Regression test testInvalidDisplayIdWithFullArgumentsReturnsMessage() in tests/src/Kernel/Plugin/AiFunctionCall/UpdateViewPluginsTest.php calls the tool with a wrong display ID and every other argument present, and asserts the readable output is the plain "does not exist" message rather than an uncaught exception propagating out of the test.

Full suite with this fix applied (isolated on its own branch): 15/15 kernel tests passing (123 assertions) in UpdateViewPluginsTest, no failures.

API changes

None. This is a bug fix to existing, already-broken behaviour - no new context parameters, no signature changes, no config schema changes.

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jibran created an issue. See original summary.

jibran’s picture

Status: Active » Needs review
jibran’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • jibran committed 643bdea4 on 1.0.x
    fix: #3621935 Fix agent process crash on a guessed, wrong display ID