[wp-trac] [WordPress Trac] #64406: PHP 8.x TypeError in wp_delete_object_term_relationships() when taxonomy not registered
WordPress Trac
noreply at wordpress.org
Fri Dec 12 05:30:26 UTC 2025
#64406: PHP 8.x TypeError in wp_delete_object_term_relationships() when taxonomy
not registered
----------------------------+------------------------------
Reporter: owolter | Owner: (none)
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Taxonomy | Version: 6.9
Severity: normal | Resolution:
Keywords: php8 has-patch | Focuses:
----------------------------+------------------------------
Description changed by westonruter:
Old description:
> # WordPress Core Bug Report
>
> ## Summary
> PHP 8.x TypeError in `wp_delete_object_term_relationships()` when
> taxonomy is not registered during deletion
>
> ## Description
> The function `wp_delete_object_term_relationships()` in `wp-
> includes/taxonomy.php` does not check if `wp_get_object_terms()` returns
> a `WP_Error` object before passing the result to `array_map()`. This
> causes a fatal TypeError in PHP 8.0+ when attempting to delete
> attachments if a taxonomy is not properly registered at the time of the
> AJAX request.
>
> ## Steps to Reproduce
> 1. Have a WordPress installation with custom attachment taxonomies
> 2. Create a scenario where `post_tag` (or another taxonomy) is not
> registered during admin AJAX calls (e.g., through plugin load order
> issues, early AJAX execution)
> 3. Attempt to delete a media library item via wp-admin
> 4. Fatal error occurs
>
> ## Expected Behavior
> Attachment deletion should complete successfully even if a taxonomy
> returns a `WP_Error`, or at minimum should fail gracefully with a logged
> error rather than a fatal PHP error.
>
> ## Actual Behavior
> Fatal TypeError crashes the deletion process:
> ```
> PHP Fatal error: Uncaught TypeError: array_map(): Argument #2 ($array)
> must be of type array, WP_Error given in /wp-includes/taxonomy.php:2002
> Stack trace:
> #0 /wp-includes/taxonomy.php(2002): array_map()
> #1 /wp-includes/post.php(6743): wp_delete_object_term_relationships()
> #2 /wp-includes/post.php(3799): wp_delete_attachment()
> #3 /wp-admin/includes/ajax-actions.php(889): wp_delete_post()
> ```
>
> ## Technical Details
>
> **WordPress Version:** 6.9
> **PHP Version:** 8.3 (also affects 8.0, 8.1, 8.2, 8.4)
> **File:** `wp-includes/taxonomy.php`
> **Line:** ~2002
> **Function:** `wp_delete_object_term_relationships()`
>
> ### Root Cause
> The WordPress Codex documents that `wp_get_object_terms()` can return
> `WP_Error`, but `wp_delete_object_term_relationships()` assumes it always
> returns an array. In PHP 7.x this would fail silently or produce a
> warning, but PHP 8.x's strict type checking for built-in functions makes
> this a fatal error.
>
> **Current code (lines 1999-2003):**
> ```php
> foreach ( (array) $taxonomies as $taxonomy ) {
> $term_ids = wp_get_object_terms( $object_id, $taxonomy, array(
> 'fields' => 'ids' ) );
> $term_ids = array_map( 'intval', $term_ids );
> wp_remove_object_terms( $object_id, $term_ids, $taxonomy );
> }
> ```
>
> ## Proposed Fix
> Add a `WP_Error` check before calling `array_map()`:
>
> ```php
> foreach ( (array) $taxonomies as $taxonomy ) {
> $term_ids = wp_get_object_terms( $object_id, $taxonomy, array(
> 'fields' => 'ids' ) );
> if ( is_wp_error( $term_ids ) ) {
> continue;
> }
> $term_ids = array_map( 'intval', $term_ids );
> wp_remove_object_terms( $object_id, $term_ids, $taxonomy );
> }
> ```
>
> Alternatively, for better debugging:
> ```php
> foreach ( (array) $taxonomies as $taxonomy ) {
> $term_ids = wp_get_object_terms( $object_id, $taxonomy, array(
> 'fields' => 'ids' ) );
> if ( is_wp_error( $term_ids ) ) {
> // Log error but continue deletion process
> error_log( sprintf(
> 'Error retrieving terms for taxonomy "%s" on object %d: %s',
> $taxonomy,
> $object_id,
> $term_ids->get_error_message()
> ) );
> continue;
> }
> $term_ids = array_map( 'intval', $term_ids );
> wp_remove_object_terms( $object_id, $term_ids, $taxonomy );
> }
> ```
>
> ## Impact
> This is a **defensive programming issue**. While the underlying cause
> (taxonomy not registered) may vary by installation, WordPress core should
> handle `WP_Error` returns from its own functions gracefully rather than
> causing fatal errors. This affects PHP 8.0+ users and will become more
> prevalent as PHP 7.x reaches end-of-life.
>
> ## Additional Context
> This issue was discovered when attempting to delete media library items
> on a WordPress 6.9 installation running PHP 8.3. The error occurred
> because `post_tag` taxonomy was not registered during the AJAX deletion
> request, causing `wp_get_object_terms()` to return a `WP_Error` with the
> message "Invalid taxonomy".
>
> While the specific trigger may be environment-dependent, the lack of
> error handling is a core issue that should be addressed for PHP 8.x
> compatibility and general code robustness.
New description:
# WordPress Core Bug Report
= Summary
PHP 8.x TypeError in `wp_delete_object_term_relationships()` when taxonomy
is not registered during deletion
== Description
The function `wp_delete_object_term_relationships()` in `wp-
includes/taxonomy.php` does not check if `wp_get_object_terms()` returns a
`WP_Error` object before passing the result to `array_map()`. This causes
a fatal TypeError in PHP 8.0+ when attempting to delete attachments if a
taxonomy is not properly registered at the time of the AJAX request.
== Steps to Reproduce
1. Have a WordPress installation with custom attachment taxonomies
2. Create a scenario where `post_tag` (or another taxonomy) is not
registered during admin AJAX calls (e.g., through plugin load order
issues, early AJAX execution)
3. Attempt to delete a media library item via wp-admin
4. Fatal error occurs
== Expected Behavior
Attachment deletion should complete successfully even if a taxonomy
returns a `WP_Error`, or at minimum should fail gracefully with a logged
error rather than a fatal PHP error.
== Actual Behavior
Fatal TypeError crashes the deletion process:
{{{
PHP Fatal error: Uncaught TypeError: array_map(): Argument #2 ($array)
must be of type array, WP_Error given in /wp-includes/taxonomy.php:2002
Stack trace:
#0 /wp-includes/taxonomy.php(2002): array_map()
#1 /wp-includes/post.php(6743): wp_delete_object_term_relationships()
#2 /wp-includes/post.php(3799): wp_delete_attachment()
#3 /wp-admin/includes/ajax-actions.php(889): wp_delete_post()
}}}
== Technical Details
**WordPress Version:** 6.9
**PHP Version:** 8.3 (also affects 8.0, 8.1, 8.2, 8.4)
**File:** `wp-includes/taxonomy.php`
**Line:** ~2002
**Function:** `wp_delete_object_term_relationships()`
=== Root Cause
The WordPress Codex documents that `wp_get_object_terms()` can return
`WP_Error`, but `wp_delete_object_term_relationships()` assumes it always
returns an array. In PHP 7.x this would fail silently or produce a
warning, but PHP 8.x's strict type checking for built-in functions makes
this a fatal error.
**Current code (lines 1999-2003):**
{{{#!php
<?php
foreach ( (array) $taxonomies as $taxonomy ) {
$term_ids = wp_get_object_terms( $object_id, $taxonomy, array(
'fields' => 'ids' ) );
$term_ids = array_map( 'intval', $term_ids );
wp_remove_object_terms( $object_id, $term_ids, $taxonomy );
}
}}}
== Proposed Fix
Add a `WP_Error` check before calling `array_map()`:
{{{#!php
<?php
foreach ( (array) $taxonomies as $taxonomy ) {
$term_ids = wp_get_object_terms( $object_id, $taxonomy, array(
'fields' => 'ids' ) );
if ( is_wp_error( $term_ids ) ) {
continue;
}
$term_ids = array_map( 'intval', $term_ids );
wp_remove_object_terms( $object_id, $term_ids, $taxonomy );
}
}}}
Alternatively, for better debugging:
{{{#!php
<?php
foreach ( (array) $taxonomies as $taxonomy ) {
$term_ids = wp_get_object_terms( $object_id, $taxonomy, array(
'fields' => 'ids' ) );
if ( is_wp_error( $term_ids ) ) {
// Log error but continue deletion process
error_log( sprintf(
'Error retrieving terms for taxonomy "%s" on object %d: %s',
$taxonomy,
$object_id,
$term_ids->get_error_message()
) );
continue;
}
$term_ids = array_map( 'intval', $term_ids );
wp_remove_object_terms( $object_id, $term_ids, $taxonomy );
}
}}}
== Impact
This is a **defensive programming issue**. While the underlying cause
(taxonomy not registered) may vary by installation, WordPress core should
handle `WP_Error` returns from its own functions gracefully rather than
causing fatal errors. This affects PHP 8.0+ users and will become more
prevalent as PHP 7.x reaches end-of-life.
== Additional Context
This issue was discovered when attempting to delete media library items on
a WordPress 6.9 installation running PHP 8.3. The error occurred because
`post_tag` taxonomy was not registered during the AJAX deletion request,
causing `wp_get_object_terms()` to return a `WP_Error` with the message
"Invalid taxonomy".
While the specific trigger may be environment-dependent, the lack of error
handling is a core issue that should be addressed for PHP 8.x
compatibility and general code robustness.
--
--
Ticket URL: <https://core.trac.wordpress.org/ticket/64406#comment:1>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list