Make WordPress Core

Opened 4 weeks ago

Closed 3 weeks ago

Last modified 3 weeks ago

#65058 closed defect (bug) (fixed)

Abilities API: Catch exceptions thrown by ability callbacks

Reported by: gziolo's profile gziolo Owned by: gziolo's profile gziolo
Milestone: 7.0 Priority: normal
Severity: normal Version: 6.9
Component: Abilities API Keywords: abilities-api has-patch has-unit-tests commit dev-reviewed
Focuses: Cc:

Description

Originally reported at https://github.com/WordPress/ai/issues/392.

Description

When testing the Core AI feature in WordPress 7.0 RC, I encountered an issue while regenerating a post title.

Actual behavior:

A network error occurs:

cURL error 28: Operation timed out after 30006 milliseconds with 0 bytes received
In the browser console:
A 500 Internal Server Error is logged
The response unexpectedly includes the entire HTML of the page

Also noticed:
wp.abilities.executeAbility is unavailable. Falling back to REST.

Why this is an issue:

Returning full HTML in API response may indicate improper error handling
Could expose unintended data or create debugging/security concerns

Additional Notes:

Issue seems related to the request sent to:

https://router.huggingface.co/v1/chat/completions
Possibly caused by API timeout, but response handling appears incorrect

Step-by-step reproduction instructions

  1. Created a new post
  2. Entered blog title and content
  3. Clicked on “Re-generate” title option
  4. Checked the console log

Environment info

WordPress Version: 7.0 RC (Beta)
Feature: Core AI (Title Generation)
Browser: Chrome (latest)
Setup: Local/Development environment

Change History (10)

This ticket was mentioned in PR #11544 on WordPress/wordpress-develop by @gziolo.


4 weeks ago
#1

  • Keywords has-patch has-unit-tests added

## 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 https://github.com/WordPress/ai/issues/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.

## Test plan

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

🤖 Generated with Claude Code

#2 @gziolo
4 weeks ago

  • Keywords dev-feedback added

#3 @gziolo
4 weeks ago

  • Keywords commit added
  • Owner set to gziolo
  • Status changed from new to reviewing

#4 @gziolo
4 weeks ago

Self-assigning for review and commi, but I'd like to get another committer to review this as well since we're in RC.

This ticket was mentioned in Slack in #core-ai by gziolo. View the logs.


4 weeks ago

#6 @jorbin
3 weeks ago

  • Keywords dev-reviewed added; dev-feedback removed

#7 @pavanpatil1
3 weeks ago

Patch Testing Report

Patch Tested: https://github.com/WordPress/wordpress-develop/pull/11544

Environment
Playground
WordPress: 7.0-RC2
PHP: 7.4.33
Server: nginx/1.29.4
Browser: Chrome
OS: macOS

Result:

The patch is working fine, and no console errors appear when generating the title. ✅

Screenshot:
Before fix: https://www.awesomescreenshot.com/image/59847079?key=4dfc4a8276de7c09255c6494d9b332e3
After fix: https://www.awesomescreenshot.com/image/59847180?key=b07e03ee3043738e9b1ee6a9832eca8b

#8 @gziolo
3 weeks ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 62238:

Abilities API: Catch exceptions thrown by ability callbacks and return 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: https://github.com/WordPress/wordpress-develop/pull/11544

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

#9 @gziolo
3 weeks ago

In 62240:

Abilities API: Catch exceptions thrown by ability callbacks and return 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: https://github.com/WordPress/wordpress-develop/pull/11544

Reviewed by adamsilverstein, justlevine, jorbin.
Merges [62238] to the 7.0 branch.

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

#10 @desrosj
3 weeks ago

  • Component changed from AI to Abilities API

Moving tickets related to the Abilities API to a new sub-component.

Note: See TracTickets for help on using tickets.