Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Validation on omitted fields not triggered in edition '2023' with protovalidate #292

Closed
tkaur-ds opened this issue Jan 11, 2025 · 1 comment
Labels
Bug Something isn't working

Comments

@tkaur-ds
Copy link

Description

When using Protobuf edition = "2023", the validation on omitted fields does not trigger. In contrast, when using syntax = "proto3" without the edition, omitted fields are validated as having their default value (empty string). This causes an issue where required validations like min_len don't trigger for omitted fields in edition "2023", but they do work when the field is explicitly set (even as an empty string).

Steps to Reproduce

  1. Define a simple Protobuf message with a string field that has min_len validation.
  2. Without edition = "2023", compile and validate the Protobuf message, and omit the field in the request.
  3. With edition = "2023", compile and validate the same Protobuf message, and omit the field in the request.

Protobuf Example:

syntax = "proto3";
// syntax = "proto3";  // Case 1: Without edition
edition = "2023";  // Case 2: With edition "2023"

import "buf/validate/validate.proto";

// Service definition
service MyService {
  rpc MyMethod(MyRequest) returns (MyResponse);
}

// Request message with validation on string fields
message MyRequest {
  string start_date = 1 [(buf.validate.field).string = {
    min_len: 1
  }];
}

// Response message
message MyResponse {
  string message = 1;
}

Request Example (Omitting start_date):

{}

Expected Behavior

When using syntax = "proto3", if the field start_date is omitted (empty object {}), validation should still trigger, and an error should be raised because the field defaults to an empty string (which fails the min_len validation).

When using edition = "2023", if the start_date field is omitted, validation should also trigger an error due to the min_len: 1 constraint. The field should not be treated as "missing" and should trigger validation.

Actual Behavior

  • With syntax = "proto3" (without edition), if the field is omitted, validation triggers because it defaults to an empty string, and the min_len: 1 validation error is raised.
  • With edition = "2023", if the field is omitted, no validation occurs at all. The field is treated as missing, and the min_len: 1 validation does not trigger.

Screenshots/Logs

  • No error is shown when the field is omitted in edition = "2023".
  • The error message "start_date must have at least 1 character" is shown when using syntax = "proto3".

Environment

  • Protobuf Compiler & Version: buf 1.49.0
  • Protovalidate Version: v0.9.0

Possible Solution

It seems like edition "2023" treats omitted fields differently than proto3 by not applying validation if the field is omitted. A potential fix could be to treat omitted fields in edition "2023" as having default values (similar to proto3) so that validation can trigger for min_len and other constraints.

Additional Context

  • This issue only occurs when edition = "2023" is used in the Protobuf definition.
  • If the field is explicitly included in the request (even with an empty string), validation works as expected.
@tkaur-ds tkaur-ds added the Bug Something isn't working label Jan 11, 2025
@nicksnyder
Copy link
Member

nicksnyder commented Jan 12, 2025

This is not a bug in Protovalidate. Protovalidate's behavior is different here because there is a difference in behavior between proto3 and edition 2023.

In proto3, no specified field rule (i.e. not marking the field as "optional") defaults to implicit presence.
In edition 2023, no specified field rule (i.e. not marking the field as "optional") defaults to explicit presence.
This is documented here: https://protobuf.dev/editions/overview/#proto3-syntax

The min_len protovalidate rule only checks a value if it is present. As defined above, if a field is not set it is implicitly present in proto3, so the rule applies and fails. If you switch to edition 2023, then the field is not present when you validate a {} message, so the rule doesn't apply.

You can verify that this is what is causing the different behavior by adding this line to your edition 2023 file to keep the proto3 behavior:

option features.field_presence = IMPLICIT;

What you really want to do though is just to mark the field as required. That will ensure the field is set and has a minimum length of 1. Like this:

edition = "2023";

import "buf/validate/validate.proto";

package playground;

// Request message with validation on string fields
message MyRequest {
  string start_date = 1 [
    (buf.validate.field).string.min_len = 1,
    (buf.validate.field).required = true
  ];
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants