Make WordPress Core

Opened 8 hours ago

Last modified 55 minutes ago

#66436 new enhancement

rest_validate_value_from_schema() should be able to report every validation error, not only the first

Reported by: zaguiini Owned by:
Priority: normal Milestone: Awaiting Review
Component: REST API Version:
Severity: normal Keywords:
Cc: Focuses:

Description

rest_validate_value_from_schema() stops at the first property that fails. In rest_validate_object_value_from_schema() the loop over properties returns the first WP_Error it meets (wp-includes/rest-api.php:2444-2449 in 7.1.4), and the same happens for pattern properties and for array items. A request with three bad fields produces one error, the client fixes it, sends again, and learns about the next one.

This was acceptable when a person read the error. It is costly for a program that talks to WordPress through the REST API or the Abilities API: each round trip is a full request, and an AI agent that calls an ability retries the same call once per bad field. The Abilities API validates ability input with this function (WP_Ability::validate_input(), wp-includes/abilities-api/class-wp-ability.php:536), so every ability on a site has this behavior and no plugin can change it without re-implementing the validator.

I propose that the validator can collect every error. A WP_Error already carries several codes and messages, so the result shape exists. Two options:

  1. A new argument or a filterable flag, off by default, that makes rest_validate_value_from_schema() continue after a failure and return one WP_Error with every failing property, each with its own message and data.param.
  2. A separate function, such as rest_validate_value_from_schema_all(), that returns every error, with rest_validate_value_from_schema() unchanged.

Either way, the Abilities API could use it in validate_input() so an ability reports every invalid field in one response. I am happy to work on a patch once the direction is agreed.

Change History (1)

#1 @sukhendu2002
55 minutes ago

I confirmed that this still applies on trunk: object properties, pattern properties, additional properties, array items, and missing required properties stop at the first failure.

An explicit opt-in argument, disabled by default, seems worth exploring. That would preserve existing behavior while allowing callers such as the Abilities API to request all validation errors.

There are two details to account for before implementing this:

  • WP_Ability::validate_input() currently wraps only the first message from the validator. It would also need to preserve the collected errors.
  • Simply merging errors into one WP_Error does not preserve the proposed per-error data.param association through REST serialization. When several failures share a code such as rest_invalid_type, rest_convert_error_to_response() attaches the latest data for that code to every message. Each failure therefore needs a representation that keeps its code, message, and parameter path together.

It would also help to clarify whether “every error” means all failing fields or every failed constraint within each field, and how errors from anyOf/oneOf alternatives should be presented.

One small update to the description: trunk now has the wp_ability_validate_input filter, which allows plugins to augment or replace the result. It does not provide aggregate schema validation, so the underlying enhancement remains relevant.

Note: See TracTickets for help on using tickets.