[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