Skip to content

Abilities: Catch exceptions thrown by ability callbacks#11544

Open
gziolo wants to merge 1 commit intoWordPress:trunkfrom
gziolo:fix/abilities-callback-exceptions
Open

Abilities: Catch exceptions thrown by ability callbacks#11544
gziolo wants to merge 1 commit intoWordPress:trunkfrom
gziolo:fix/abilities-callback-exceptions

Conversation

@gziolo
Copy link
Copy Markdown
Member

@gziolo gziolo commented Apr 10, 2026

Summary

When an ability's execute_callback or permission_callback throws an uncaught exception, it propagates through WP_Ability::execute() and the REST run controller, causing WordPress to render an HTML fatal error page with a 500 status instead of a JSON error response.

This was first reported via the Core AI feature plugin when an AI connector's HTTP request to a remote provider timed out after 30 seconds — the underlying client threw a ServerException, which surfaced to the browser as a full HTML page inside the REST response, breaking client-side error handling.

See WordPress/ai#392 for the original report and root-cause analysis.

Fix

WP_Ability::invoke_callback() now catches any Throwable raised by the callback and converts it to a WP_Error with code ability_callback_exception. Because invoke_callback() is shared between do_execute() and check_permissions(), both callback types are protected by a single change, and the existing is_wp_error() handling in execute() surfaces the error to the caller unchanged.

Trac ticket: https://core.trac.wordpress.org/ticket/65058

Test plan

  • New unit test covers an execute_callback that throws — expects WP_Error with code ability_callback_exception.
  • New unit test covers a permission_callback that throws via check_permissions() directly — same code, same behavior.

🤖 Generated with Claude Code

Converts any `Throwable` raised by an `execute_callback` or `permission_callback`
into a `WP_Error` with code `ability_callback_exception`, instead of letting it
propagate uncaught. This prevents the REST ability runner from surfacing a
500 HTML fatal error page when a callback fails (e.g. an AI connector HTTP
timeout), and gives clients a predictable JSON error response.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props gziolo.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions
Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant