Skip to content

REST API: Allow resetting meta keys with nothing stored to null - #14845

Open
dannflorea wants to merge 2 commits into
WordPress:trunkfrom
dannflorea:fix-unset-meta-null-reset
Open

dannflorea wants to merge 2 commits into
WordPress:trunkfrom
dannflorea:fix-unset-meta-null-reset

Conversation

@dannflorea

Copy link
Copy Markdown

Trac ticket: https://core.trac.wordpress.org/ticket/66377

What

When a single meta key has nothing stored, WP_REST_Meta_Fields::update_value() validated the empty string returned by get_metadata() before a null reset. For boolean, integer, number and enum keys that fails, so the request was rejected with a 500 rest_invalid_stored_value even though nothing was stored.

This reads the current value with get_metadata_raw(), which returns null when no row exists, and only validates when there is a stored value. A stored value that fails the schema, including a stored empty string, is still protected.

This also fixes echoing back comment meta: the core _wp_note_status key (enum, no default) is returned as null when unset, and sending it back previously failed with a 500.

Tests

  • test_set_value_to_null_with_nothing_stored: null for unset boolean, integer, number and enum keys returns 200 and creates no row.
  • test_set_value_to_null_with_invalid_empty_string_stored: a stored empty string on a boolean key is still protected (500, row kept).
  • test_update_comment_with_meta_echoed_back_from_response: updating a comment with the meta from its own GET response returns 200.

Testing instructions

  1. Register register_post_meta( 'post', 'repro_flag', array( 'type' => 'boolean', 'single' => true, 'show_in_rest' => true ) );
  2. On a post without that key, POST /wp/v2/posts/<id> with {"meta":{"repro_flag":null}}.
  3. Before: 500 rest_invalid_stored_value. After: 200.

Verified with WordPress Playground (trunk nightly, PHP 8.3). I did not run PHPUnit locally; relying on CI.

Only validate the current value of a single meta key before a null reset when a value is actually stored, so unset boolean, integer and enum keys no longer fail with rest_invalid_stored_value.

See #66377.
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs.

Core Committers: Use this line as a base for the props when committing in SVN:

Props maxdevagency, westonruter.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

@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.

$current = get_metadata_raw( $this->get_meta_type(), $object_id, $meta_key, true );

if ( is_wp_error( rest_validate_value_from_schema( $current, $args['schema'] ) ) ) {
if ( null !== $current && is_wp_error( rest_validate_value_from_schema( $current, $args['schema'] ) ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In the case of null, get_metadata() falls back to get_metadata_default(). So this means that the fallback value doesn't need to be obtained here, since the null case is checked. So this seems right to me.

Comment thread tests/phpunit/tests/rest-api/rest-post-meta-fields.php Outdated
Comment thread tests/phpunit/tests/rest-api/rest-post-meta-fields.php Outdated
Comment thread tests/phpunit/tests/rest-api/rest-post-meta-fields.php Outdated
Comment thread tests/phpunit/tests/rest-api/rest-post-meta-fields.php Outdated
Comment thread tests/phpunit/tests/rest-api/rest-post-meta-fields.php Outdated
Tests: Add type hints suggested in review.

Co-authored-by: Weston Ruter <westonruter@gmail.com>
@dannflorea

Copy link
Copy Markdown
Author

Thanks for the review, @westonruter! I've applied all the type suggestions. And thanks for confirming the get_metadata_raw() reasoning: since the null case is handled, the default fallback isn't needed there.

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.

2 participants