[wp-trac] [WordPress Trac] #65240: REST API: WP_REST_Plugins_Controller::create_item() fatals when plugins_api response lacks language_packs property
WordPress Trac
noreply at wordpress.org
Thu May 14 12:35:49 UTC 2026
#65240: REST API: WP_REST_Plugins_Controller::create_item() fatals when plugins_api
response lacks language_packs property
-----------------------------------------+-----------------------------
Reporter: flipcreative | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: REST API | Version: 6.9.4
Severity: normal | Keywords: needs-patch
Focuses: rest-api, php-compatibility |
-----------------------------------------+-----------------------------
When installing a plugin via the REST endpoint `POST /wp/v2/plugins`,
`WP_REST_Plugins_Controller::create_item()` calls `plugins_api(
'plugin_information', ... )` requesting `language_packs => true`, then
immediately runs `array_map()` over `$api->language_packs` without
checking whether the property is set or is an array.
If the API response does not include a populated `language_packs` key —
which can happen when the plugin has no translation packs on
translate.wordpress.org for any installed locale, when wp.org returns a
partial response, or when the result is filtered by a third party —
accessing `$api->language_packs` produces a PHP Warning, then immediately
triggers a Fatal TypeError on the array_map call. Both originate from the
same request.
The install itself has already succeeded by the time the fatal fires —
`$upgrader->install( $api->download_link )` runs and completes before the
language pack section is reached, so the plugin files are on disk. The
REST response returns a 500 even though the install succeeded. This causes
spurious error UI in any caller that uses this endpoint and produces noisy
logs in production. We are seeing this consistently in the wild from at
least one widely deployed third-party caller (Elementor One's app
installer) and the volume is enough that one major managed WordPress host
has flagged the resulting 500 spike to customers.
**File:** `wp-includes/rest-api/endpoints/class-wp-rest-plugins-
controller.php`
**Offending code (around lines 380–385):**
```php
$language_packs = array_map(
static function ( $item ) {
return (object) $item;
},
$api->language_packs
);
```
**Error output:**
```
PHP Warning: Undefined property: stdClass::$language_packs in
/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php on
line 387
PHP Fatal error: Uncaught TypeError: array_map(): Argument #2 ($array)
must be of type
array, null given in /wp-includes/rest-api/endpoints/class-wp-rest-
plugins-controller.php:383
```
**Steps to reproduce:**
1. Send an authenticated `POST` request to `/wp-json/wp/v2/plugins` with a
`slug` for a plugin whose `plugins_api` response does not contain a
populated `language_packs` array.
2. Observe that the plugin is correctly installed to `wp-content/plugins`.
3. Observe that the REST request returns HTTP 500.
4. Observe the warning and fatal in the PHP error log.
**Suggested fix:**
Guard the array_map call:
```php
$language_packs = array();
if ( ! empty( $api->language_packs ) && is_array( $api->language_packs ) )
{
$language_packs = array_map(
static function ( $item ) {
return (object) $item;
},
$api->language_packs
);
}
```
Alternatively, normalize the `plugins_api` response so that
`language_packs` is always present as an array (even empty) when requested
via the `fields` parameter.
**Environment:**
- WordPress 6.9.4
- PHP 8.x (the strict TypeError behavior requires PHP 8.0+)
- Reproduced on WP Engine hosting
**Related tickets (same defensive-coding pattern):**
- #44582 — Undefined property stdClass::$plugin
- #59413 — Undefined property stdClass::$plugin in class-wp-automatic-
updater.php
- #46382 — Undefined property stdClass::$current in class-walker-nav-
menu.php
This is part of a broader pattern of WP core code paths that trust
stdClass properties on API responses without guards. The fix here is one-
line and low-risk.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/65240>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list