Skip to content

Abilities: Catch exceptions thrown by ability callbacks#11544

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

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

github-actions bot commented Apr 10, 2026

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, adamsilverstein, justlevine, jorbin.

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.

Copy link
Copy Markdown
Member

@adamsilverstein adamsilverstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic

Copy link
Copy Markdown

@justlevine justlevine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love it!

Copy link
Copy Markdown
Member

@aaronjorbin aaronjorbin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks!

@gziolo gziolo added the props-bot Adding this label triggers the Props Bot workflow for a PR. label Apr 16, 2026
@github-actions github-actions bot removed the props-bot Adding this label triggers the Props Bot workflow for a PR. label Apr 16, 2026
pento pushed a commit that referenced this pull request Apr 16, 2026
…n WP_Error.

Wraps `invoke_callback()` in a try/catch so that exceptions thrown by execute or permission callbacks are converted to a `WP_Error` with the `ability_callback_exception` code instead of propagating as uncaught throwables.

Developed in: #11544

Props priyankagusani, jamesgiroux, jeffpaul, dkotter, adamsilverstein, justlevine, jorbin, pavanpatil1.
Fixes #65058.



git-svn-id: https://develop.svn.wordpress.org/trunk@62238 602fd350-edb4-49c9-b593-d223f7449a82
@github-actions
Copy link
Copy Markdown

A commit was made that fixes the Trac ticket referenced in the description of this pull request.

SVN changeset: 62238
GitHub commit: 42388b5

This PR will be closed, but please confirm the accuracy of this and reopen if there is more work to be done.

@github-actions github-actions bot closed this Apr 16, 2026
@gziolo gziolo deleted the fix/abilities-callback-exceptions branch April 16, 2026 07:23
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Apr 16, 2026
…n WP_Error.

Wraps `invoke_callback()` in a try/catch so that exceptions thrown by execute or permission callbacks are converted to a `WP_Error` with the `ability_callback_exception` code instead of propagating as uncaught throwables.

Developed in: WordPress/wordpress-develop#11544

Props priyankagusani, jamesgiroux, jeffpaul, dkotter, adamsilverstein, justlevine, jorbin, pavanpatil1.
Fixes #65058.


Built from https://develop.svn.wordpress.org/trunk@62238


git-svn-id: http://core.svn.wordpress.org/trunk@61518 1a063a9b-81f0-0310-95a4-ce76da25c4cd
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.

4 participants