Protorip

buf.validate

Messages

Rule represents a validation rule written in the Common Expression Language (CEL) syntax. Each Rule includes a unique identifier, an optional error message, and the CEL expression to evaluate. For more information, see our documentation.

message Foo {
option (buf.validate.message).cel = {
id: "foo.bar"
message: "bar must be greater than 0"
expression: "this.bar > 0"
};
int32 bar = 1;
}
NameTagTypeLabelDescription
id1stringoptional

id is a string that serves as a machine-readable name for this Rule. It should be unique within its scope, which could be either a message or a field.

message2stringoptional

message is an optional field that provides a human-readable error message for this Rule when the CEL expression evaluates to false. If a non-empty message is provided, any strings resulting from the CEL expression evaluation are ignored.

expression3stringoptional

expression is the actual CEL expression that will be evaluated for validation. This string must resolve to either a boolean or a string value. If the expression evaluates to false or a non-empty string, the validation is considered failed, and the message is rejected.

MessageRules represents validation rules that are applied to the entire message. It includes disabling options and a list of Rule messages representing Common Expression Language (CEL) validation rules.

NameTagTypeLabelDescription
cel_expression5stringrepeated

cel_expression is a repeated field CEL expressions. Each expression specifies a validation rule to be applied to this message. These rules are written in Common Expression Language (CEL) syntax.

This is a simplified form of the cel Rule field, where only expression is set. This allows for simpler syntax when defining CEL Rules where id and message derived from the expression. id will be same as the expression.

For more information, see our documentation.

message MyMessage {
// The field `foo` must be greater than 42.
option (buf.validate.message).cel_expression = "this.foo > 42";
// The field `foo` must be less than 84.
option (buf.validate.message).cel_expression = "this.foo < 84";
optional int32 foo = 1;
}
cel3Rulerepeated

cel is a repeated field of type Rule. Each Rule specifies a validation rule to be applied to this message. These rules are written in Common Expression Language (CEL) syntax. For more information, see our documentation.

message MyMessage {
// The field `foo` must be greater than 42.
option (buf.validate.message).cel = {
id: "my_message.value",
message: "must be greater than 42",
expression: "this.foo > 42",
};
optional int32 foo = 1;
}
oneof4MessageOneofRulerepeated

oneof is a repeated field of type MessageOneofRule that specifies a list of fields of which at most one can be present. If required is also specified, then exactly one of the specified fields must be present.

This will enforce oneof-like constraints with a few features not provided by actual Protobuf oneof declarations:

  1. Repeated and map fields are allowed in this validation. In a Protobuf oneof, only scalar fields are allowed.
  2. Fields with implicit presence are allowed. In a Protobuf oneof, all member fields have explicit presence. This means that, for the purpose of determining how many fields are set, explicitly setting such a field to its zero value is effectively the same as not setting it at all.
  3. This will always generate validation errors for a message unmarshalled from serialized data that sets more than one field. With a Protobuf oneof, when multiple fields are present in the serialized form, earlier values are usually silently ignored when unmarshalling, with only the last field being set when unmarshalling completes.

Note that adding a field to a oneof will also set the IGNORE_IF_ZERO_VALUE on the fields. This means only the field that is set will be validated and the unset fields are not validated according to the field rules. This behavior can be overridden by setting ignore against a field.

message MyMessage {
// Only one of `field1` or `field2` _can_ be present in this message.
option (buf.validate.message).oneof = { fields: ["field1", "field2"] };
// Exactly one of `field3` or `field4` _must_ be present in this message.
option (buf.validate.message).oneof = { fields: ["field3", "field4"], required: true };
string field1 = 1;
bytes field2 = 2;
bool field3 = 3;
int32 field4 = 4;
}
NameTagTypeLabelDescription
fields1stringrepeated

A list of field names to include in the oneof. All field names must be defined in the message. At least one field must be specified, and duplicates are not permitted.

required2booloptional

If true, one of the fields specified must be set.

The OneofRules message type enables you to manage rules for oneof fields in your protobuf messages.

NameTagTypeLabelDescription
required1booloptional

If required is true, exactly one field of the oneof must be set. A validation error is returned if no fields in the oneof are set. Further rules should be placed on the fields themselves to ensure they are valid values, such as min_len or gt.

message MyMessage {
oneof value {
// Either `a` or `b` must be set. If `a` is set, it must also be
// non-empty; whereas if `b` is set, it can still be an empty string.
option (buf.validate.oneof).required = true;
string a = 1 [(buf.validate.field).string.min_len = 1];
string b = 2;
}
}

FieldRules encapsulates the rules for each type of field. Depending on the field, the correct set should be used to ensure proper validations.

NameTagTypeLabelDescription
cel_expression29stringrepeated

cel_expression is a repeated field CEL expressions. Each expression specifies a validation rule to be applied to this message. These rules are written in Common Expression Language (CEL) syntax.

This is a simplified form of the cel Rule field, where only expression is set. This allows for simpler syntax when defining CEL Rules where id and message derived from the expression. id will be same as the expression.

For more information, see our documentation.

message MyMessage {
// The field `value` must be greater than 42.
optional int32 value = 1 [(buf.validate.field).cel_expression = "this > 42"];
}
cel23Rulerepeated

cel is a repeated field used to represent a textual expression in the Common Expression Language (CEL) syntax. For more information, see our documentation.

message MyMessage {
// The field `value` must be greater than 42.
optional int32 value = 1 [(buf.validate.field).cel = {
id: "my_message.value",
message: "must be greater than 42",
expression: "this > 42",
}];
}
required25booloptional

If required is true, the field must be set. A validation error is returned if the field is not set.

syntax="proto3";

message FieldsWithPresence {
// Requires any string to be set, including the empty string.
optional string link = 1 [
(buf.validate.field).required = true
];
// Requires true or false to be set.
optional bool disabled = 2 [
(buf.validate.field).required = true
];
// Requires a message to be set, including the empty message.
SomeMessage msg = 4 [
(buf.validate.field).required = true
];
}

All fields in the example above track presence. By default, Protovalidate ignores rules on those fields if no value is set. required ensures that the fields are set and valid.

Fields that don't track presence are always validated by Protovalidate, whether they are set or not. It is not necessary to add required. It can be added to indicate that the field cannot be the zero value.

syntax="proto3";

message FieldsWithoutPresence {
// `string.email` always applies, even to an empty string.
string link = 1 [
(buf.validate.field).string.email = true
];
// `repeated.min_items` always applies, even to an empty list.
repeated string labels = 2 [
(buf.validate.field).repeated.min_items = 1
];
// `required`, for fields that don't track presence, indicates
// the value of the field can't be the zero value.
int32 zero_value_not_allowed = 3 [
(buf.validate.field).required = true
];
}

To learn which fields track presence, see the Field Presence cheat sheet.

Note: While field rules can be applied to repeated items, map keys, and map values, the elements are always considered to be set. Consequently, specifying repeated.items.required is redundant.

ignore27Ignoreoptional

Ignore validation rules on the field if its value matches the specified criteria. See the Ignore enum for details.

message UpdateRequest {
// The uri rule only applies if the field is not an empty string.
string url = 1 [
(buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE,
(buf.validate.field).string.uri = true
];
}
float1FloatRulesoptional

Scalar Field Types

double2DoubleRulesoptional
int323Int32Rulesoptional
int644Int64Rulesoptional
uint325UInt32Rulesoptional
uint646UInt64Rulesoptional
sint327SInt32Rulesoptional
sint648SInt64Rulesoptional
fixed329Fixed32Rulesoptional
fixed6410Fixed64Rulesoptional
sfixed3211SFixed32Rulesoptional
sfixed6412SFixed64Rulesoptional
bool13BoolRulesoptional
string14StringRulesoptional
bytes15BytesRulesoptional
enum16EnumRulesoptional

Complex Field Types

repeated18RepeatedRulesoptional
map19MapRulesoptional
any20AnyRulesoptional

Well-Known Field Types

duration21DurationRulesoptional
field_mask28FieldMaskRulesoptional
timestamp22TimestampRulesoptional

PredefinedRules are custom rules that can be re-used with multiple fields.

NameTagTypeLabelDescription
cel1Rulerepeated

cel is a repeated field used to represent a textual expression in the Common Expression Language (CEL) syntax. For more information, see our documentation.

message MyMessage {
// The field `value` must be greater than 42.
optional int32 value = 1 [(buf.validate.predefined).cel = {
id: "my_message.value",
message: "must be greater than 42",
expression: "this > 42",
}];
}

FloatRules describes the rules applied to float values. These rules may also be applied to the google.protobuf.FloatValue Well-Known-Type.

NameTagTypeLabelDescription
const1floatoptional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyFloat {
// value must equal 42.0
float value = 1 [(buf.validate.field).float.const = 42.0];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "float.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2floatoptional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MyFloat {
// must be less than 10.0
float value = 1 [(buf.validate.field).float.lt = 10.0];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "float.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && (this.isNan() || this >= rules.lt)? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3floatoptional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MyFloat {
// must be less than or equal to 10.0
float value = 1 [(buf.validate.field).float.lte = 10.0];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "float.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && (this.isNan() || this > rules.lte)? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4floatoptional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyFloat {
// must be greater than 5.0 [float.gt]
float value = 1 [(buf.validate.field).float.gt = 5.0];

// must be greater than 5 and less than 10.0 [float.gt_lt]
float other_value = 2 [(buf.validate.field).float = { gt: 5.0, lt: 10.0 }];

// must be greater than 10 or less than 5.0 [float.gt_lt_exclusive]
float another_value = 3 [(buf.validate.field).float = { gt: 10.0, lt: 5.0 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "float.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && (this.isNan() || this <= rules.gt)? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "float.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this.isNan() || this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "float.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (this.isNan() || (rules.lt <= this && this <= rules.gt))? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "float.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this.isNan() || this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "float.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (this.isNan() || (rules.lte < this && this <= rules.gt))? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5floatoptional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyFloat {
// must be greater than or equal to 5.0 [float.gte]
float value = 1 [(buf.validate.field).float.gte = 5.0];

// must be greater than or equal to 5.0 and less than 10.0 [float.gte_lt]
float other_value = 2 [(buf.validate.field).float = { gte: 5.0, lt: 10.0 }];

// must be greater than or equal to 10.0 or less than 5.0 [float.gte_lt_exclusive]
float another_value = 3 [(buf.validate.field).float = { gte: 10.0, lt: 5.0 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "float.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && (this.isNan() || this < rules.gte)? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "float.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this.isNan() || this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "float.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (this.isNan() || (rules.lt <= this && this < rules.gte))? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "float.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this.isNan() || this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "float.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (this.isNan() || (rules.lte < this && this < rules.gte))? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6floatrepeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MyFloat {
// must be in list [1.0, 2.0, 3.0]
float value = 1 [(buf.validate.field).float = { in: [1.0, 2.0, 3.0] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "float.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7floatrepeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MyFloat {
// value must not be in list [1.0, 2.0, 3.0]
float value = 1 [(buf.validate.field).float = { not_in: [1.0, 2.0, 3.0] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "float.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
finite8booloptional

finite requires the field value to be finite. If the field value is infinite or NaN, an error message is generated.

(buf.validate.predefined)
{
  "cel": {
    "id": "float.finite",
    "expression": "rules.finite ? (this.isNan() || this.isInf() ? 'must be finite' : '') : ''"
  }
}
example9floatrepeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyFloat {
float value = 1 [
(buf.validate.field).float.example = 1.0,
(buf.validate.field).float.example = inf
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "float.example",
    "expression": "true"
  }
}

DoubleRules describes the rules applied to double values. These rules may also be applied to the google.protobuf.DoubleValue Well-Known-Type.

NameTagTypeLabelDescription
const1doubleoptional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyDouble {
// value must equal 42.0
double value = 1 [(buf.validate.field).double.const = 42.0];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "double.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2doubleoptional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MyDouble {
// must be less than 10.0
double value = 1 [(buf.validate.field).double.lt = 10.0];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "double.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && (this.isNan() || this >= rules.lt)? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3doubleoptional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MyDouble {
// must be less than or equal to 10.0
double value = 1 [(buf.validate.field).double.lte = 10.0];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "double.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && (this.isNan() || this > rules.lte)? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4doubleoptional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyDouble {
// must be greater than 5.0 [double.gt]
double value = 1 [(buf.validate.field).double.gt = 5.0];

// must be greater than 5 and less than 10.0 [double.gt_lt]
double other_value = 2 [(buf.validate.field).double = { gt: 5.0, lt: 10.0 }];

// must be greater than 10 or less than 5.0 [double.gt_lt_exclusive]
double another_value = 3 [(buf.validate.field).double = { gt: 10.0, lt: 5.0 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "double.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && (this.isNan() || this <= rules.gt)? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "double.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this.isNan() || this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "double.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (this.isNan() || (rules.lt <= this && this <= rules.gt))? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "double.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this.isNan() || this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "double.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (this.isNan() || (rules.lte < this && this <= rules.gt))? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5doubleoptional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyDouble {
// must be greater than or equal to 5.0 [double.gte]
double value = 1 [(buf.validate.field).double.gte = 5.0];

// must be greater than or equal to 5.0 and less than 10.0 [double.gte_lt]
double other_value = 2 [(buf.validate.field).double = { gte: 5.0, lt: 10.0 }];

// must be greater than or equal to 10.0 or less than 5.0 [double.gte_lt_exclusive]
double another_value = 3 [(buf.validate.field).double = { gte: 10.0, lt: 5.0 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "double.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && (this.isNan() || this < rules.gte)? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "double.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this.isNan() || this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "double.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (this.isNan() || (rules.lt <= this && this < rules.gte))? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "double.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this.isNan() || this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "double.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (this.isNan() || (rules.lte < this && this < rules.gte))? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6doublerepeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MyDouble {
// must be in list [1.0, 2.0, 3.0]
double value = 1 [(buf.validate.field).double = { in: [1.0, 2.0, 3.0] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "double.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7doublerepeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MyDouble {
// value must not be in list [1.0, 2.0, 3.0]
double value = 1 [(buf.validate.field).double = { not_in: [1.0, 2.0, 3.0] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "double.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
finite8booloptional

finite requires the field value to be finite. If the field value is infinite or NaN, an error message is generated.

(buf.validate.predefined)
{
  "cel": {
    "id": "double.finite",
    "expression": "rules.finite ? (this.isNan() || this.isInf() ? 'must be finite' : '') : ''"
  }
}
example9doublerepeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyDouble {
double value = 1 [
(buf.validate.field).double.example = 1.0,
(buf.validate.field).double.example = inf
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "double.example",
    "expression": "true"
  }
}

Int32Rules describes the rules applied to int32 values. These rules may also be applied to the google.protobuf.Int32Value Well-Known-Type.

NameTagTypeLabelDescription
const1int32optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyInt32 {
// value must equal 42
int32 value = 1 [(buf.validate.field).int32.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int32.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2int32optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MyInt32 {
// must be less than 10
int32 value = 1 [(buf.validate.field).int32.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int32.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3int32optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MyInt32 {
// must be less than or equal to 10
int32 value = 1 [(buf.validate.field).int32.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int32.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4int32optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyInt32 {
// must be greater than 5 [int32.gt]
int32 value = 1 [(buf.validate.field).int32.gt = 5];

// must be greater than 5 and less than 10 [int32.gt_lt]
int32 other_value = 2 [(buf.validate.field).int32 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [int32.gt_lt_exclusive]
int32 another_value = 3 [(buf.validate.field).int32 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "int32.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "int32.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "int32.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "int32.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "int32.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5int32optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyInt32 {
// must be greater than or equal to 5 [int32.gte]
int32 value = 1 [(buf.validate.field).int32.gte = 5];

// must be greater than or equal to 5 and less than 10 [int32.gte_lt]
int32 other_value = 2 [(buf.validate.field).int32 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [int32.gte_lt_exclusive]
int32 another_value = 3 [(buf.validate.field).int32 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "int32.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "int32.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "int32.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "int32.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "int32.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6int32repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MyInt32 {
// must be in list [1, 2, 3]
int32 value = 1 [(buf.validate.field).int32 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int32.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7int32repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MyInt32 {
// value must not be in list [1, 2, 3]
int32 value = 1 [(buf.validate.field).int32 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int32.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8int32repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyInt32 {
int32 value = 1 [
(buf.validate.field).int32.example = 1,
(buf.validate.field).int32.example = -10
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int32.example",
    "expression": "true"
  }
}

Int64Rules describes the rules applied to int64 values. These rules may also be applied to the google.protobuf.Int64Value Well-Known-Type.

NameTagTypeLabelDescription
const1int64optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyInt64 {
// value must equal 42
int64 value = 1 [(buf.validate.field).int64.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int64.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2int64optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MyInt64 {
// must be less than 10
int64 value = 1 [(buf.validate.field).int64.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int64.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3int64optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MyInt64 {
// must be less than or equal to 10
int64 value = 1 [(buf.validate.field).int64.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int64.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4int64optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyInt64 {
// must be greater than 5 [int64.gt]
int64 value = 1 [(buf.validate.field).int64.gt = 5];

// must be greater than 5 and less than 10 [int64.gt_lt]
int64 other_value = 2 [(buf.validate.field).int64 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [int64.gt_lt_exclusive]
int64 another_value = 3 [(buf.validate.field).int64 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "int64.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "int64.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "int64.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "int64.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "int64.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5int64optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyInt64 {
// must be greater than or equal to 5 [int64.gte]
int64 value = 1 [(buf.validate.field).int64.gte = 5];

// must be greater than or equal to 5 and less than 10 [int64.gte_lt]
int64 other_value = 2 [(buf.validate.field).int64 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [int64.gte_lt_exclusive]
int64 another_value = 3 [(buf.validate.field).int64 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "int64.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "int64.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "int64.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "int64.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "int64.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6int64repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MyInt64 {
// must be in list [1, 2, 3]
int64 value = 1 [(buf.validate.field).int64 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int64.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7int64repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MyInt64 {
// value must not be in list [1, 2, 3]
int64 value = 1 [(buf.validate.field).int64 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int64.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example9int64repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyInt64 {
int64 value = 1 [
(buf.validate.field).int64.example = 1,
(buf.validate.field).int64.example = -10
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "int64.example",
    "expression": "true"
  }
}

UInt32Rules describes the rules applied to uint32 values. These rules may also be applied to the google.protobuf.UInt32Value Well-Known-Type.

NameTagTypeLabelDescription
const1uint32optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyUInt32 {
// value must equal 42
uint32 value = 1 [(buf.validate.field).uint32.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint32.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2uint32optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MyUInt32 {
// must be less than 10
uint32 value = 1 [(buf.validate.field).uint32.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint32.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3uint32optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MyUInt32 {
// must be less than or equal to 10
uint32 value = 1 [(buf.validate.field).uint32.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint32.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4uint32optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyUInt32 {
// must be greater than 5 [uint32.gt]
uint32 value = 1 [(buf.validate.field).uint32.gt = 5];

// must be greater than 5 and less than 10 [uint32.gt_lt]
uint32 other_value = 2 [(buf.validate.field).uint32 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [uint32.gt_lt_exclusive]
uint32 another_value = 3 [(buf.validate.field).uint32 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "uint32.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "uint32.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "uint32.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "uint32.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "uint32.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5uint32optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyUInt32 {
// must be greater than or equal to 5 [uint32.gte]
uint32 value = 1 [(buf.validate.field).uint32.gte = 5];

// must be greater than or equal to 5 and less than 10 [uint32.gte_lt]
uint32 other_value = 2 [(buf.validate.field).uint32 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [uint32.gte_lt_exclusive]
uint32 another_value = 3 [(buf.validate.field).uint32 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "uint32.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "uint32.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "uint32.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "uint32.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "uint32.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6uint32repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MyUInt32 {
// must be in list [1, 2, 3]
uint32 value = 1 [(buf.validate.field).uint32 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint32.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7uint32repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MyUInt32 {
// value must not be in list [1, 2, 3]
uint32 value = 1 [(buf.validate.field).uint32 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint32.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8uint32repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyUInt32 {
uint32 value = 1 [
(buf.validate.field).uint32.example = 1,
(buf.validate.field).uint32.example = 10
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint32.example",
    "expression": "true"
  }
}

UInt64Rules describes the rules applied to uint64 values. These rules may also be applied to the google.protobuf.UInt64Value Well-Known-Type.

NameTagTypeLabelDescription
const1uint64optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyUInt64 {
// value must equal 42
uint64 value = 1 [(buf.validate.field).uint64.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint64.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2uint64optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MyUInt64 {
// must be less than 10
uint64 value = 1 [(buf.validate.field).uint64.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint64.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3uint64optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MyUInt64 {
// must be less than or equal to 10
uint64 value = 1 [(buf.validate.field).uint64.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint64.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4uint64optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyUInt64 {
// must be greater than 5 [uint64.gt]
uint64 value = 1 [(buf.validate.field).uint64.gt = 5];

// must be greater than 5 and less than 10 [uint64.gt_lt]
uint64 other_value = 2 [(buf.validate.field).uint64 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [uint64.gt_lt_exclusive]
uint64 another_value = 3 [(buf.validate.field).uint64 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "uint64.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "uint64.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "uint64.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "uint64.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "uint64.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5uint64optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyUInt64 {
// must be greater than or equal to 5 [uint64.gte]
uint64 value = 1 [(buf.validate.field).uint64.gte = 5];

// must be greater than or equal to 5 and less than 10 [uint64.gte_lt]
uint64 other_value = 2 [(buf.validate.field).uint64 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [uint64.gte_lt_exclusive]
uint64 another_value = 3 [(buf.validate.field).uint64 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "uint64.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "uint64.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "uint64.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "uint64.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "uint64.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6uint64repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MyUInt64 {
// must be in list [1, 2, 3]
uint64 value = 1 [(buf.validate.field).uint64 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint64.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7uint64repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MyUInt64 {
// value must not be in list [1, 2, 3]
uint64 value = 1 [(buf.validate.field).uint64 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint64.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8uint64repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyUInt64 {
uint64 value = 1 [
(buf.validate.field).uint64.example = 1,
(buf.validate.field).uint64.example = 10
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "uint64.example",
    "expression": "true"
  }
}

SInt32Rules describes the rules applied to sint32 values.

NameTagTypeLabelDescription
const1sint32optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MySInt32 {
// value must equal 42
sint32 value = 1 [(buf.validate.field).sint32.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint32.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2sint32optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MySInt32 {
// must be less than 10
sint32 value = 1 [(buf.validate.field).sint32.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint32.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3sint32optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MySInt32 {
// must be less than or equal to 10
sint32 value = 1 [(buf.validate.field).sint32.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint32.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4sint32optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MySInt32 {
// must be greater than 5 [sint32.gt]
sint32 value = 1 [(buf.validate.field).sint32.gt = 5];

// must be greater than 5 and less than 10 [sint32.gt_lt]
sint32 other_value = 2 [(buf.validate.field).sint32 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [sint32.gt_lt_exclusive]
sint32 another_value = 3 [(buf.validate.field).sint32 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "sint32.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "sint32.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "sint32.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "sint32.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "sint32.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5sint32optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MySInt32 {
// must be greater than or equal to 5 [sint32.gte]
sint32 value = 1 [(buf.validate.field).sint32.gte = 5];

// must be greater than or equal to 5 and less than 10 [sint32.gte_lt]
sint32 other_value = 2 [(buf.validate.field).sint32 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [sint32.gte_lt_exclusive]
sint32 another_value = 3 [(buf.validate.field).sint32 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "sint32.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "sint32.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "sint32.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "sint32.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "sint32.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6sint32repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MySInt32 {
// must be in list [1, 2, 3]
sint32 value = 1 [(buf.validate.field).sint32 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint32.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7sint32repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MySInt32 {
// value must not be in list [1, 2, 3]
sint32 value = 1 [(buf.validate.field).sint32 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint32.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8sint32repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MySInt32 {
sint32 value = 1 [
(buf.validate.field).sint32.example = 1,
(buf.validate.field).sint32.example = -10
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint32.example",
    "expression": "true"
  }
}

SInt64Rules describes the rules applied to sint64 values.

NameTagTypeLabelDescription
const1sint64optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MySInt64 {
// value must equal 42
sint64 value = 1 [(buf.validate.field).sint64.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint64.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2sint64optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MySInt64 {
// must be less than 10
sint64 value = 1 [(buf.validate.field).sint64.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint64.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3sint64optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MySInt64 {
// must be less than or equal to 10
sint64 value = 1 [(buf.validate.field).sint64.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint64.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4sint64optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MySInt64 {
// must be greater than 5 [sint64.gt]
sint64 value = 1 [(buf.validate.field).sint64.gt = 5];

// must be greater than 5 and less than 10 [sint64.gt_lt]
sint64 other_value = 2 [(buf.validate.field).sint64 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [sint64.gt_lt_exclusive]
sint64 another_value = 3 [(buf.validate.field).sint64 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "sint64.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "sint64.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "sint64.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "sint64.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "sint64.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5sint64optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MySInt64 {
// must be greater than or equal to 5 [sint64.gte]
sint64 value = 1 [(buf.validate.field).sint64.gte = 5];

// must be greater than or equal to 5 and less than 10 [sint64.gte_lt]
sint64 other_value = 2 [(buf.validate.field).sint64 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [sint64.gte_lt_exclusive]
sint64 another_value = 3 [(buf.validate.field).sint64 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "sint64.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "sint64.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "sint64.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "sint64.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "sint64.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6sint64repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MySInt64 {
// must be in list [1, 2, 3]
sint64 value = 1 [(buf.validate.field).sint64 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint64.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7sint64repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MySInt64 {
// value must not be in list [1, 2, 3]
sint64 value = 1 [(buf.validate.field).sint64 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint64.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8sint64repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MySInt64 {
sint64 value = 1 [
(buf.validate.field).sint64.example = 1,
(buf.validate.field).sint64.example = -10
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sint64.example",
    "expression": "true"
  }
}

Fixed32Rules describes the rules applied to fixed32 values.

NameTagTypeLabelDescription
const1fixed32optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyFixed32 {
// value must equal 42
fixed32 value = 1 [(buf.validate.field).fixed32.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed32.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2fixed32optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MyFixed32 {
// must be less than 10
fixed32 value = 1 [(buf.validate.field).fixed32.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed32.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3fixed32optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MyFixed32 {
// must be less than or equal to 10
fixed32 value = 1 [(buf.validate.field).fixed32.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed32.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4fixed32optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyFixed32 {
// must be greater than 5 [fixed32.gt]
fixed32 value = 1 [(buf.validate.field).fixed32.gt = 5];

// must be greater than 5 and less than 10 [fixed32.gt_lt]
fixed32 other_value = 2 [(buf.validate.field).fixed32 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [fixed32.gt_lt_exclusive]
fixed32 another_value = 3 [(buf.validate.field).fixed32 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "fixed32.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "fixed32.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "fixed32.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "fixed32.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "fixed32.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5fixed32optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyFixed32 {
// must be greater than or equal to 5 [fixed32.gte]
fixed32 value = 1 [(buf.validate.field).fixed32.gte = 5];

// must be greater than or equal to 5 and less than 10 [fixed32.gte_lt]
fixed32 other_value = 2 [(buf.validate.field).fixed32 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [fixed32.gte_lt_exclusive]
fixed32 another_value = 3 [(buf.validate.field).fixed32 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "fixed32.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "fixed32.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "fixed32.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "fixed32.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "fixed32.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6fixed32repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MyFixed32 {
// must be in list [1, 2, 3]
fixed32 value = 1 [(buf.validate.field).fixed32 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed32.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7fixed32repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MyFixed32 {
// value must not be in list [1, 2, 3]
fixed32 value = 1 [(buf.validate.field).fixed32 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed32.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8fixed32repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyFixed32 {
fixed32 value = 1 [
(buf.validate.field).fixed32.example = 1,
(buf.validate.field).fixed32.example = 2
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed32.example",
    "expression": "true"
  }
}

Fixed64Rules describes the rules applied to fixed64 values.

NameTagTypeLabelDescription
const1fixed64optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyFixed64 {
// value must equal 42
fixed64 value = 1 [(buf.validate.field).fixed64.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed64.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2fixed64optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MyFixed64 {
// must be less than 10
fixed64 value = 1 [(buf.validate.field).fixed64.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed64.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3fixed64optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MyFixed64 {
// must be less than or equal to 10
fixed64 value = 1 [(buf.validate.field).fixed64.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed64.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4fixed64optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyFixed64 {
// must be greater than 5 [fixed64.gt]
fixed64 value = 1 [(buf.validate.field).fixed64.gt = 5];

// must be greater than 5 and less than 10 [fixed64.gt_lt]
fixed64 other_value = 2 [(buf.validate.field).fixed64 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [fixed64.gt_lt_exclusive]
fixed64 another_value = 3 [(buf.validate.field).fixed64 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "fixed64.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "fixed64.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "fixed64.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "fixed64.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "fixed64.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5fixed64optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyFixed64 {
// must be greater than or equal to 5 [fixed64.gte]
fixed64 value = 1 [(buf.validate.field).fixed64.gte = 5];

// must be greater than or equal to 5 and less than 10 [fixed64.gte_lt]
fixed64 other_value = 2 [(buf.validate.field).fixed64 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [fixed64.gte_lt_exclusive]
fixed64 another_value = 3 [(buf.validate.field).fixed64 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "fixed64.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "fixed64.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "fixed64.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "fixed64.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "fixed64.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6fixed64repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MyFixed64 {
// must be in list [1, 2, 3]
fixed64 value = 1 [(buf.validate.field).fixed64 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed64.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7fixed64repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MyFixed64 {
// value must not be in list [1, 2, 3]
fixed64 value = 1 [(buf.validate.field).fixed64 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed64.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8fixed64repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyFixed64 {
fixed64 value = 1 [
(buf.validate.field).fixed64.example = 1,
(buf.validate.field).fixed64.example = 2
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "fixed64.example",
    "expression": "true"
  }
}

SFixed32Rules describes the rules applied to fixed32 values.

NameTagTypeLabelDescription
const1sfixed32optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MySFixed32 {
// value must equal 42
sfixed32 value = 1 [(buf.validate.field).sfixed32.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed32.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2sfixed32optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MySFixed32 {
// must be less than 10
sfixed32 value = 1 [(buf.validate.field).sfixed32.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed32.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3sfixed32optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MySFixed32 {
// must be less than or equal to 10
sfixed32 value = 1 [(buf.validate.field).sfixed32.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed32.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4sfixed32optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MySFixed32 {
// must be greater than 5 [sfixed32.gt]
sfixed32 value = 1 [(buf.validate.field).sfixed32.gt = 5];

// must be greater than 5 and less than 10 [sfixed32.gt_lt]
sfixed32 other_value = 2 [(buf.validate.field).sfixed32 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [sfixed32.gt_lt_exclusive]
sfixed32 another_value = 3 [(buf.validate.field).sfixed32 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "sfixed32.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "sfixed32.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "sfixed32.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "sfixed32.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "sfixed32.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5sfixed32optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MySFixed32 {
// must be greater than or equal to 5 [sfixed32.gte]
sfixed32 value = 1 [(buf.validate.field).sfixed32.gte = 5];

// must be greater than or equal to 5 and less than 10 [sfixed32.gte_lt]
sfixed32 other_value = 2 [(buf.validate.field).sfixed32 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [sfixed32.gte_lt_exclusive]
sfixed32 another_value = 3 [(buf.validate.field).sfixed32 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "sfixed32.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "sfixed32.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "sfixed32.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "sfixed32.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "sfixed32.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6sfixed32repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MySFixed32 {
// must be in list [1, 2, 3]
sfixed32 value = 1 [(buf.validate.field).sfixed32 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed32.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7sfixed32repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MySFixed32 {
// value must not be in list [1, 2, 3]
sfixed32 value = 1 [(buf.validate.field).sfixed32 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed32.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8sfixed32repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MySFixed32 {
sfixed32 value = 1 [
(buf.validate.field).sfixed32.example = 1,
(buf.validate.field).sfixed32.example = 2
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed32.example",
    "expression": "true"
  }
}

SFixed64Rules describes the rules applied to fixed64 values.

NameTagTypeLabelDescription
const1sfixed64optional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MySFixed64 {
// value must equal 42
sfixed64 value = 1 [(buf.validate.field).sfixed64.const = 42];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed64.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt2sfixed64optional

lt requires the field value to be less than the specified value (field < value). If the field value is equal to or greater than the specified value, an error message is generated.

message MySFixed64 {
// must be less than 10
sfixed64 value = 1 [(buf.validate.field).sfixed64.lt = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed64.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte3sfixed64optional

lte requires the field value to be less than or equal to the specified value (field <= value). If the field value is greater than the specified value, an error message is generated.

message MySFixed64 {
// must be less than or equal to 10
sfixed64 value = 1 [(buf.validate.field).sfixed64.lte = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed64.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt4sfixed64optional

gt requires the field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MySFixed64 {
// must be greater than 5 [sfixed64.gt]
sfixed64 value = 1 [(buf.validate.field).sfixed64.gt = 5];

// must be greater than 5 and less than 10 [sfixed64.gt_lt]
sfixed64 other_value = 2 [(buf.validate.field).sfixed64 = { gt: 5, lt: 10 }];

// must be greater than 10 or less than 5 [sfixed64.gt_lt_exclusive]
sfixed64 another_value = 3 [(buf.validate.field).sfixed64 = { gt: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "sfixed64.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "sfixed64.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "sfixed64.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "sfixed64.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "sfixed64.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte5sfixed64optional

gte requires the field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MySFixed64 {
// must be greater than or equal to 5 [sfixed64.gte]
sfixed64 value = 1 [(buf.validate.field).sfixed64.gte = 5];

// must be greater than or equal to 5 and less than 10 [sfixed64.gte_lt]
sfixed64 other_value = 2 [(buf.validate.field).sfixed64 = { gte: 5, lt: 10 }];

// must be greater than or equal to 10 or less than 5 [sfixed64.gte_lt_exclusive]
sfixed64 another_value = 3 [(buf.validate.field).sfixed64 = { gte: 10, lt: 5 }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "sfixed64.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "sfixed64.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "sfixed64.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "sfixed64.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "sfixed64.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in6sfixed64repeated

in requires the field value to be equal to one of the specified values. If the field value isn't one of the specified values, an error message is generated.

message MySFixed64 {
// must be in list [1, 2, 3]
sfixed64 value = 1 [(buf.validate.field).sfixed64 = { in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed64.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in7sfixed64repeated

not_in requires the field value to not be equal to any of the specified values. If the field value is one of the specified values, an error message is generated.

message MySFixed64 {
// value must not be in list [1, 2, 3]
sfixed64 value = 1 [(buf.validate.field).sfixed64 = { not_in: [1, 2, 3] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed64.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example8sfixed64repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MySFixed64 {
sfixed64 value = 1 [
(buf.validate.field).sfixed64.example = 1,
(buf.validate.field).sfixed64.example = 2
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "sfixed64.example",
    "expression": "true"
  }
}

BoolRules describes the rules applied to bool values. These rules may also be applied to the google.protobuf.BoolValue Well-Known-Type.

NameTagTypeLabelDescription
const1booloptional

const requires the field value to exactly match the specified boolean value. If the field value doesn't match, an error message is generated.

message MyBool {
// value must equal true
bool value = 1 [(buf.validate.field).bool.const = true];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bool.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
example2boolrepeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyBool {
bool value = 1 [
(buf.validate.field).bool.example = true,
(buf.validate.field).bool.example = false
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bool.example",
    "expression": "true"
  }
}

StringRules describes the rules applied to string values These rules may also be applied to the google.protobuf.StringValue Well-Known-Type.

NameTagTypeLabelDescription
const1stringoptional

const requires the field value to exactly match the specified value. If the field value doesn't match, an error message is generated.

message MyString {
// value must equal `hello`
string value = 1 [(buf.validate.field).string.const = "hello"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.const",
    "expression": "this != getField(rules, 'const') ? 'must equal `%s`'.format([getField(rules, 'const')]) : ''"
  }
}
len19uint64optional

len dictates that the field value must have the specified number of characters (Unicode code points), which may differ from the number of bytes in the string. If the field value does not meet the specified length, an error message will be generated.

message MyString {
// value length must be 5 characters
string value = 1 [(buf.validate.field).string.len = 5];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.len",
    "expression": "uint(this.size()) != rules.len ? 'must be %s characters'.format([rules.len]) : ''"
  }
}
min_len2uint64optional

min_len specifies that the field value must have at least the specified number of characters (Unicode code points), which may differ from the number of bytes in the string. If the field value contains fewer characters, an error message will be generated.

message MyString {
// value length must be at least 3 characters
string value = 1 [(buf.validate.field).string.min_len = 3];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.min_len",
    "expression": "uint(this.size()) < rules.min_len ? 'must be at least %s characters'.format([rules.min_len]) : ''"
  }
}
max_len3uint64optional

max_len specifies that the field value must have no more than the specified number of characters (Unicode code points), which may differ from the number of bytes in the string. If the field value contains more characters, an error message will be generated.

message MyString {
// value length must be at most 10 characters
string value = 1 [(buf.validate.field).string.max_len = 10];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.max_len",
    "expression": "uint(this.size()) > rules.max_len ? 'must be at most %s characters'.format([rules.max_len]) : ''"
  }
}
len_bytes20uint64optional

len_bytes dictates that the field value must have the specified number of bytes. If the field value does not match the specified length in bytes, an error message will be generated.

message MyString {
// value length must be 6 bytes
string value = 1 [(buf.validate.field).string.len_bytes = 6];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.len_bytes",
    "expression": "uint(bytes(this).size()) != rules.len_bytes ? 'must be %s bytes'.format([rules.len_bytes]) : ''"
  }
}
min_bytes4uint64optional

min_bytes specifies that the field value must have at least the specified number of bytes. If the field value contains fewer bytes, an error message will be generated.

message MyString {
// value length must be at least 4 bytes
string value = 1 [(buf.validate.field).string.min_bytes = 4];
}

(buf.validate.predefined)
{
  "cel": {
    "id": "string.min_bytes",
    "expression": "uint(bytes(this).size()) < rules.min_bytes ? 'must be at least %s bytes'.format([rules.min_bytes]) : ''"
  }
}
max_bytes5uint64optional

max_bytes specifies that the field value must have no more than the specified number of bytes. If the field value contains more bytes, an error message will be generated.

message MyString {
// value length must be at most 8 bytes
string value = 1 [(buf.validate.field).string.max_bytes = 8];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.max_bytes",
    "expression": "uint(bytes(this).size()) > rules.max_bytes ? 'must be at most %s bytes'.format([rules.max_bytes]) : ''"
  }
}
pattern6stringoptional

pattern specifies that the field value must match the specified regular expression (RE2 syntax), with the expression provided without any delimiters. If the field value doesn't match the regular expression, an error message will be generated.

message MyString {
// value does not match regex pattern `^[a-zA-Z]//$`
string value = 1 [(buf.validate.field).string.pattern = "^[a-zA-Z]//$"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.pattern",
    "expression": "!this.matches(rules.pattern) ? 'does not match regex pattern `%s`'.format([rules.pattern]) : ''"
  }
}
prefix7stringoptional

prefix specifies that the field value must have the specified substring at the beginning of the string. If the field value doesn't start with the specified prefix, an error message will be generated.

message MyString {
// value does not have prefix `pre`
string value = 1 [(buf.validate.field).string.prefix = "pre"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.prefix",
    "expression": "!this.startsWith(rules.prefix) ? 'does not have prefix `%s`'.format([rules.prefix]) : ''"
  }
}
suffix8stringoptional

suffix specifies that the field value must have the specified substring at the end of the string. If the field value doesn't end with the specified suffix, an error message will be generated.

message MyString {
// value does not have suffix `post`
string value = 1 [(buf.validate.field).string.suffix = "post"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.suffix",
    "expression": "!this.endsWith(rules.suffix) ? 'does not have suffix `%s`'.format([rules.suffix]) : ''"
  }
}
contains9stringoptional

contains specifies that the field value must have the specified substring anywhere in the string. If the field value doesn't contain the specified substring, an error message will be generated.

message MyString {
// value does not contain substring `inside`.
string value = 1 [(buf.validate.field).string.contains = "inside"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.contains",
    "expression": "!this.contains(rules.contains) ? 'does not contain substring `%s`'.format([rules.contains]) : ''"
  }
}
not_contains23stringoptional

not_contains specifies that the field value must not have the specified substring anywhere in the string. If the field value contains the specified substring, an error message will be generated.

message MyString {
// value contains substring `inside`.
string value = 1 [(buf.validate.field).string.not_contains = "inside"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.not_contains",
    "expression": "this.contains(rules.not_contains) ? 'contains substring `%s`'.format([rules.not_contains]) : ''"
  }
}
in10stringrepeated

in specifies that the field value must be equal to one of the specified values. If the field value isn't one of the specified values, an error message will be generated.

message MyString {
// must be in list ["apple", "banana"]
string value = 1 [(buf.validate.field).string = { in: ["apple", "banana"] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in11stringrepeated

not_in specifies that the field value cannot be equal to any of the specified values. If the field value is one of the specified values, an error message will be generated.

message MyString {
// value must not be in list ["orange", "grape"]
string value = 1 [(buf.validate.field).string = { not_in: ["orange", "grape"] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
email12booloptional

email specifies that the field value must be a valid email address, for example "foo@example.com".

Conforms to the definition for a valid email address from the HTML standard. Note that this standard willfully deviates from RFC 5322, which allows many unexpected forms of email addresses and will easily match a typographical error.

If the field value isn't a valid email address, an error message will be generated.

message MyString {
// must be a valid email address
string value = 1 [(buf.validate.field).string.email = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.email",
      "message": "must be a valid email address",
      "expression": "!rules.email || this == '' || this.isEmail()"
    },
    {
      "id": "string.email_empty",
      "message": "value is empty, which is not a valid email address",
      "expression": "!rules.email || this != ''"
    }
  ]
}
hostname13booloptional

hostname specifies that the field value must be a valid hostname, for example "foo.example.com".

A valid hostname follows the rules below:

  • The name consists of one or more labels, separated by a dot (".").
  • Each label can be 1 to 63 alphanumeric characters.
  • A label can contain hyphens ("-"), but must not start or end with a hyphen.
  • The right-most label must not be digits only.
  • The name can have a trailing dot—for example, "foo.example.com.".
  • The name can be 253 characters at most, excluding the optional trailing dot.

If the field value isn't a valid hostname, an error message will be generated.

message MyString {
// must be a valid hostname
string value = 1 [(buf.validate.field).string.hostname = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.hostname",
      "message": "must be a valid hostname",
      "expression": "!rules.hostname || this == '' || this.isHostname()"
    },
    {
      "id": "string.hostname_empty",
      "message": "value is empty, which is not a valid hostname",
      "expression": "!rules.hostname || this != ''"
    }
  ]
}
ip14booloptional

ip specifies that the field value must be a valid IP (v4 or v6) address.

IPv4 addresses are expected in the dotted decimal format—for example, "192.168.5.21". IPv6 addresses are expected in their text representation—for example, "::1", or "2001:0DB8:ABCD:0012::0".

Both formats are well-defined in the internet standard RFC 3986. Zone identifiers for IPv6 addresses (for example, "fe80::a%en1") are supported.

If the field value isn't a valid IP address, an error message will be generated.

message MyString {
// must be a valid IP address
string value = 1 [(buf.validate.field).string.ip = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ip",
      "message": "must be a valid IP address",
      "expression": "!rules.ip || this == '' || this.isIp()"
    },
    {
      "id": "string.ip_empty",
      "message": "value is empty, which is not a valid IP address",
      "expression": "!rules.ip || this != ''"
    }
  ]
}
ipv415booloptional

ipv4 specifies that the field value must be a valid IPv4 address—for example "192.168.5.21". If the field value isn't a valid IPv4 address, an error message will be generated.

message MyString {
// must be a valid IPv4 address
string value = 1 [(buf.validate.field).string.ipv4 = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ipv4",
      "message": "must be a valid IPv4 address",
      "expression": "!rules.ipv4 || this == '' || this.isIp(4)"
    },
    {
      "id": "string.ipv4_empty",
      "message": "value is empty, which is not a valid IPv4 address",
      "expression": "!rules.ipv4 || this != ''"
    }
  ]
}
ipv616booloptional

ipv6 specifies that the field value must be a valid IPv6 address—for example "::1", or "d7a:115c:a1e0:ab12:4843:cd96:626b:430b". If the field value is not a valid IPv6 address, an error message will be generated.

message MyString {
// must be a valid IPv6 address
string value = 1 [(buf.validate.field).string.ipv6 = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ipv6",
      "message": "must be a valid IPv6 address",
      "expression": "!rules.ipv6 || this == '' || this.isIp(6)"
    },
    {
      "id": "string.ipv6_empty",
      "message": "value is empty, which is not a valid IPv6 address",
      "expression": "!rules.ipv6 || this != ''"
    }
  ]
}
uri17booloptional

uri specifies that the field value must be a valid URI, for example "https://example.com/foo/bar?baz=quux#frag".

URI is defined in the internet standard RFC 3986. Zone Identifiers in IPv6 address literals are supported (RFC 6874).

If the field value isn't a valid URI, an error message will be generated.

message MyString {
// must be a valid URI
string value = 1 [(buf.validate.field).string.uri = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.uri",
      "message": "must be a valid URI",
      "expression": "!rules.uri || this == '' || this.isUri()"
    },
    {
      "id": "string.uri_empty",
      "message": "value is empty, which is not a valid URI",
      "expression": "!rules.uri || this != ''"
    }
  ]
}
uri_ref18booloptional

uri_ref specifies that the field value must be a valid URI Reference—either a URI such as "https://example.com/foo/bar?baz=quux#frag", or a Relative Reference such as "./foo/bar?query".

URI, URI Reference, and Relative Reference are defined in the internet standard RFC 3986. Zone Identifiers in IPv6 address literals are supported (RFC 6874).

If the field value isn't a valid URI Reference, an error message will be generated.

message MyString {
// must be a valid URI Reference
string value = 1 [(buf.validate.field).string.uri_ref = true];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.uri_ref",
    "message": "must be a valid URI Reference",
    "expression": "!rules.uri_ref || this.isUriRef()"
  }
}
address21booloptional

address specifies that the field value must be either a valid hostname (for example, "example.com"), or a valid IP (v4 or v6) address (for example, "192.168.0.1", or "::1"). If the field value isn't a valid hostname or IP, an error message will be generated.

message MyString {
// must be a valid hostname, or ip address
string value = 1 [(buf.validate.field).string.address = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.address",
      "message": "must be a valid hostname, or ip address",
      "expression": "!rules.address || this == '' || this.isHostname() || this.isIp()"
    },
    {
      "id": "string.address_empty",
      "message": "value is empty, which is not a valid hostname, or ip address",
      "expression": "!rules.address || this != ''"
    }
  ]
}
uuid22booloptional

uuid specifies that the field value must be a valid UUID as defined by RFC 4122. If the field value isn't a valid UUID, an error message will be generated.

message MyString {
// must be a valid UUID
string value = 1 [(buf.validate.field).string.uuid = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.uuid",
      "message": "must be a valid UUID",
      "expression": "!rules.uuid || this == '' || this.matches('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$')"
    },
    {
      "id": "string.uuid_empty",
      "message": "value is empty, which is not a valid UUID",
      "expression": "!rules.uuid || this != ''"
    }
  ]
}
tuuid33booloptional

tuuid (trimmed UUID) specifies that the field value must be a valid UUID as defined by RFC 4122 with all dashes omitted. If the field value isn't a valid UUID without dashes, an error message will be generated.

message MyString {
// must be a valid trimmed UUID
string value = 1 [(buf.validate.field).string.tuuid = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.tuuid",
      "message": "must be a valid trimmed UUID",
      "expression": "!rules.tuuid || this == '' || this.matches('^[0-9a-fA-F]{32}$')"
    },
    {
      "id": "string.tuuid_empty",
      "message": "value is empty, which is not a valid trimmed UUID",
      "expression": "!rules.tuuid || this != ''"
    }
  ]
}
ip_with_prefixlen26booloptional

ip_with_prefixlen specifies that the field value must be a valid IP (v4 or v6) address with prefix length—for example, "192.168.5.21/16" or "2001:0DB8:ABCD:0012::F1/64". If the field value isn't a valid IP with prefix length, an error message will be generated.

message MyString {
// must be a valid IP with prefix length
string value = 1 [(buf.validate.field).string.ip_with_prefixlen = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ip_with_prefixlen",
      "message": "must be a valid IP prefix",
      "expression": "!rules.ip_with_prefixlen || this == '' || this.isIpPrefix()"
    },
    {
      "id": "string.ip_with_prefixlen_empty",
      "message": "value is empty, which is not a valid IP prefix",
      "expression": "!rules.ip_with_prefixlen || this != ''"
    }
  ]
}
ipv4_with_prefixlen27booloptional

ipv4_with_prefixlen specifies that the field value must be a valid IPv4 address with prefix length—for example, "192.168.5.21/16". If the field value isn't a valid IPv4 address with prefix length, an error message will be generated.

message MyString {
// must be a valid IPv4 address with prefix length
string value = 1 [(buf.validate.field).string.ipv4_with_prefixlen = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ipv4_with_prefixlen",
      "message": "must be a valid IPv4 address with prefix length",
      "expression": "!rules.ipv4_with_prefixlen || this == '' || this.isIpPrefix(4)"
    },
    {
      "id": "string.ipv4_with_prefixlen_empty",
      "message": "value is empty, which is not a valid IPv4 address with prefix length",
      "expression": "!rules.ipv4_with_prefixlen || this != ''"
    }
  ]
}
ipv6_with_prefixlen28booloptional

ipv6_with_prefixlen specifies that the field value must be a valid IPv6 address with prefix length—for example, "2001:0DB8:ABCD:0012::F1/64". If the field value is not a valid IPv6 address with prefix length, an error message will be generated.

message MyString {
// must be a valid IPv6 address prefix length
string value = 1 [(buf.validate.field).string.ipv6_with_prefixlen = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ipv6_with_prefixlen",
      "message": "must be a valid IPv6 address with prefix length",
      "expression": "!rules.ipv6_with_prefixlen || this == '' || this.isIpPrefix(6)"
    },
    {
      "id": "string.ipv6_with_prefixlen_empty",
      "message": "value is empty, which is not a valid IPv6 address with prefix length",
      "expression": "!rules.ipv6_with_prefixlen || this != ''"
    }
  ]
}
ip_prefix29booloptional

ip_prefix specifies that the field value must be a valid IP (v4 or v6) prefix—for example, "192.168.0.0/16" or "2001:0DB8:ABCD:0012::0/64".

The prefix must have all zeros for the unmasked bits. For example, "2001:0DB8:ABCD:0012::0/64" designates the left-most 64 bits for the prefix, and the remaining 64 bits must be zero.

If the field value isn't a valid IP prefix, an error message will be generated.

message MyString {
// must be a valid IP prefix
string value = 1 [(buf.validate.field).string.ip_prefix = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ip_prefix",
      "message": "must be a valid IP prefix",
      "expression": "!rules.ip_prefix || this == '' || this.isIpPrefix(true)"
    },
    {
      "id": "string.ip_prefix_empty",
      "message": "value is empty, which is not a valid IP prefix",
      "expression": "!rules.ip_prefix || this != ''"
    }
  ]
}
ipv4_prefix30booloptional

ipv4_prefix specifies that the field value must be a valid IPv4 prefix, for example "192.168.0.0/16".

The prefix must have all zeros for the unmasked bits. For example, "192.168.0.0/16" designates the left-most 16 bits for the prefix, and the remaining 16 bits must be zero.

If the field value isn't a valid IPv4 prefix, an error message will be generated.

message MyString {
// must be a valid IPv4 prefix
string value = 1 [(buf.validate.field).string.ipv4_prefix = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ipv4_prefix",
      "message": "must be a valid IPv4 prefix",
      "expression": "!rules.ipv4_prefix || this == '' || this.isIpPrefix(4, true)"
    },
    {
      "id": "string.ipv4_prefix_empty",
      "message": "value is empty, which is not a valid IPv4 prefix",
      "expression": "!rules.ipv4_prefix || this != ''"
    }
  ]
}
ipv6_prefix31booloptional

ipv6_prefix specifies that the field value must be a valid IPv6 prefix—for example, "2001:0DB8:ABCD:0012::0/64".

The prefix must have all zeros for the unmasked bits. For example, "2001:0DB8:ABCD:0012::0/64" designates the left-most 64 bits for the prefix, and the remaining 64 bits must be zero.

If the field value is not a valid IPv6 prefix, an error message will be generated.

message MyString {
// must be a valid IPv6 prefix
string value = 1 [(buf.validate.field).string.ipv6_prefix = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ipv6_prefix",
      "message": "must be a valid IPv6 prefix",
      "expression": "!rules.ipv6_prefix || this == '' || this.isIpPrefix(6, true)"
    },
    {
      "id": "string.ipv6_prefix_empty",
      "message": "value is empty, which is not a valid IPv6 prefix",
      "expression": "!rules.ipv6_prefix || this != ''"
    }
  ]
}
host_and_port32booloptional

host_and_port specifies that the field value must be a valid host/port pair—for example, "example.com:8080".

The host can be one of:

  • An IPv4 address in dotted decimal format—for example, "192.168.5.21".
  • An IPv6 address enclosed in square brackets—for example, "[2001:0DB8:ABCD:0012::F1]".
  • A hostname—for example, "example.com".

The port is separated by a colon. It must be non-empty, with a decimal number in the range of 0-65535, inclusive.

(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.host_and_port",
      "message": "must be a valid host (hostname or IP address) and port pair",
      "expression": "!rules.host_and_port || this == '' || this.isHostAndPort(true)"
    },
    {
      "id": "string.host_and_port_empty",
      "message": "value is empty, which is not a valid host and port pair",
      "expression": "!rules.host_and_port || this != ''"
    }
  ]
}
ulid35booloptional

ulid specifies that the field value must be a valid ULID (Universally Unique Lexicographically Sortable Identifier) as defined by the ULID specification. If the field value isn't a valid ULID, an error message will be generated.

message MyString {
// must be a valid ULID
string value = 1 [(buf.validate.field).string.ulid = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.ulid",
      "message": "must be a valid ULID",
      "expression": "!rules.ulid || this == '' || this.matches('^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$')"
    },
    {
      "id": "string.ulid_empty",
      "message": "value is empty, which is not a valid ULID",
      "expression": "!rules.ulid || this != ''"
    }
  ]
}
protobuf_fqn37booloptional

protobuf_fqn specifies that the field value must be a valid fully-qualified Protobuf name as defined by the Protobuf Language Specification.

A fully-qualified Protobuf name is a dot-separated list of Protobuf identifiers, where each identifier starts with a letter or underscore and is followed by zero or more letters, underscores, or digits.

Examples: "buf.validate", "google.protobuf.Timestamp", "my_package.MyMessage".

Note: historically, fully-qualified Protobuf names were represented with a leading dot (for example, ".buf.validate.StringRules"). Modern Protobuf does not use the leading dot, and most fully-qualified names are represented without it. Use protobuf_dot_fqn if a leading dot is required.

If the field value isn't a valid fully-qualified Protobuf name, an error message will be generated.

message MyString {
// value must be a valid fully-qualified Protobuf name
string value = 1 [(buf.validate.field).string.protobuf_fqn = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.protobuf_fqn",
      "message": "must be a valid fully-qualified Protobuf name",
      "expression": "!rules.protobuf_fqn || this == '' || this.matches('^[A-Za-z_][A-Za-z_0-9]*(\\\\.[A-Za-z_][A-Za-z_0-9]*)*$')"
    },
    {
      "id": "string.protobuf_fqn_empty",
      "message": "value is empty, which is not a valid fully-qualified Protobuf name",
      "expression": "!rules.protobuf_fqn || this != ''"
    }
  ]
}
protobuf_dot_fqn38booloptional

protobuf_dot_fqn specifies that the field value must be a valid fully-qualified Protobuf name with a leading dot, as defined by the Protobuf Language Specification.

A fully-qualified Protobuf name with a leading dot is a dot followed by a dot-separated list of Protobuf identifiers, where each identifier starts with a letter or underscore and is followed by zero or more letters, underscores, or digits.

Examples: ".buf.validate", ".google.protobuf.Timestamp", ".my_package.MyMessage".

Note: this is the historical representation of fully-qualified Protobuf names, where a leading dot denotes an absolute reference. Modern Protobuf does not use the leading dot, and most fully-qualified names are represented without it. Most users will want to use protobuf_fqn instead.

If the field value isn't a valid fully-qualified Protobuf name with a leading dot, an error message will be generated.

message MyString {
// value must be a valid fully-qualified Protobuf name with a leading dot
string value = 1 [(buf.validate.field).string.protobuf_dot_fqn = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.protobuf_dot_fqn",
      "message": "must be a valid fully-qualified Protobuf name with a leading dot",
      "expression": "!rules.protobuf_dot_fqn || this == '' || this.matches('^\\\\.[A-Za-z_][A-Za-z_0-9]*(\\\\.[A-Za-z_][A-Za-z_0-9]*)*$')"
    },
    {
      "id": "string.protobuf_dot_fqn_empty",
      "message": "value is empty, which is not a valid fully-qualified Protobuf name with a leading dot",
      "expression": "!rules.protobuf_dot_fqn || this != ''"
    }
  ]
}
well_known_regex24KnownRegexoptional

well_known_regex specifies a common well-known pattern defined as a regex. If the field value doesn't match the well-known regex, an error message will be generated.

message MyString {
// must be a valid HTTP header value
string value = 1 [(buf.validate.field).string.well_known_regex = KNOWN_REGEX_HTTP_HEADER_VALUE];
}

KnownRegex

well_known_regex contains some well-known patterns.

Name Number Description
KNOWN_REGEX_UNSPECIFIED 0
KNOWN_REGEX_HTTP_HEADER_NAME 1 HTTP header name as defined by RFC 7230
KNOWN_REGEX_HTTP_HEADER_VALUE 2 HTTP header value as defined by RFC 7230
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "string.well_known_regex.header_name",
      "message": "must be a valid HTTP header name",
      "expression": "rules.well_known_regex != 1 || this == '' || this.matches(!has(rules.strict) || rules.strict ?'^:?[0-9a-zA-Z!#$%&\\'*+-.^_|~\\x60]+$' :'^[^\\u0000\\u000A\\u000D]+$')"
    },
    {
      "id": "string.well_known_regex.header_name_empty",
      "message": "value is empty, which is not a valid HTTP header name",
      "expression": "rules.well_known_regex != 1 || this != ''"
    },
    {
      "id": "string.well_known_regex.header_value",
      "message": "must be a valid HTTP header value",
      "expression": "rules.well_known_regex != 2 || this.matches(!has(rules.strict) || rules.strict ?'^[^\\u0000-\\u0008\\u000A-\\u001F\\u007F]*$' :'^[^\\u0000\\u000A\\u000D]*$')"
    }
  ]
}
strict25booloptional

This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable strict header validation. By default, this is true, and HTTP header validations are RFC-compliant. Setting to false will enable looser validations that only disallow \r\n\0 characters, which can be used to bypass header matching rules.

message MyString {
// The field `value` must have be a valid HTTP headers, but not enforced with strict rules.
string value = 1 [(buf.validate.field).string.strict = false];
}
example34stringrepeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyString {
string value = 1 [
(buf.validate.field).string.example = "hello",
(buf.validate.field).string.example = "world"
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "string.example",
    "expression": "true"
  }
}

BytesRules describe the rules applied to bytes values. These rules may also be applied to the google.protobuf.BytesValue Well-Known-Type.

NameTagTypeLabelDescription
const1bytesoptional

const requires the field value to exactly match the specified bytes value. If the field value doesn't match, an error message is generated.

message MyBytes {
// must be "\x01\x02\x03\x04"
bytes value = 1 [(buf.validate.field).bytes.const = "\x01\x02\x03\x04"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.const",
    "expression": "this != getField(rules, 'const') ? 'must be %x'.format([getField(rules, 'const')]) : ''"
  }
}
len13uint64optional

len requires the field value to have the specified length in bytes. If the field value doesn't match, an error message is generated.

message MyBytes {
// value length must be 4 bytes.
optional bytes value = 1 [(buf.validate.field).bytes.len = 4];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.len",
    "expression": "uint(this.size()) != rules.len ? 'must be %s bytes'.format([rules.len]) : ''"
  }
}
min_len2uint64optional

min_len requires the field value to have at least the specified minimum length in bytes. If the field value doesn't meet the requirement, an error message is generated.

message MyBytes {
// value length must be at least 2 bytes.
optional bytes value = 1 [(buf.validate.field).bytes.min_len = 2];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.min_len",
    "expression": "uint(this.size()) < rules.min_len ? 'must be at least %s bytes'.format([rules.min_len]) : ''"
  }
}
max_len3uint64optional

max_len requires the field value to have at most the specified maximum length in bytes. If the field value exceeds the requirement, an error message is generated.

message MyBytes {
// must be at most 6 bytes.
optional bytes value = 1 [(buf.validate.field).bytes.max_len = 6];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.max_len",
    "expression": "uint(this.size()) > rules.max_len ? 'must be at most %s bytes'.format([rules.max_len]) : ''"
  }
}
pattern4stringoptional

pattern requires the field value to match the specified regular expression (RE2 syntax). The value of the field must be valid UTF-8 or validation will fail with a runtime error. If the field value doesn't match the pattern, an error message is generated.

message MyBytes {
// value must match regex pattern "^[a-zA-Z0-9]+$".
optional bytes value = 1 [(buf.validate.field).bytes.pattern = "^[a-zA-Z0-9]+$"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.pattern",
    "expression": "!string(this).matches(rules.pattern) ? 'must match regex pattern `%s`'.format([rules.pattern]) : ''"
  }
}
prefix5bytesoptional

prefix requires the field value to have the specified bytes at the beginning of the string. If the field value doesn't meet the requirement, an error message is generated.

message MyBytes {
// value does not have prefix \x01\x02
optional bytes value = 1 [(buf.validate.field).bytes.prefix = "\x01\x02"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.prefix",
    "expression": "!this.startsWith(rules.prefix) ? 'does not have prefix %x'.format([rules.prefix]) : ''"
  }
}
suffix6bytesoptional

suffix requires the field value to have the specified bytes at the end of the string. If the field value doesn't meet the requirement, an error message is generated.

message MyBytes {
// value does not have suffix \x03\x04
optional bytes value = 1 [(buf.validate.field).bytes.suffix = "\x03\x04"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.suffix",
    "expression": "!this.endsWith(rules.suffix) ? 'does not have suffix %x'.format([rules.suffix]) : ''"
  }
}
contains7bytesoptional

contains requires the field value to have the specified bytes anywhere in the string. If the field value doesn't meet the requirement, an error message is generated.

message MyBytes {
// value does not contain \x02\x03
optional bytes value = 1 [(buf.validate.field).bytes.contains = "\x02\x03"];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.contains",
    "expression": "!this.contains(rules.contains) ? 'does not contain %x'.format([rules.contains]) : ''"
  }
}
in8bytesrepeated

in requires the field value to be equal to one of the specified values. If the field value doesn't match any of the specified values, an error message is generated.

message MyBytes {
// value must in ["\x01\x02", "\x02\x03", "\x03\x04"]
optional bytes value = 1 [(buf.validate.field).bytes = { in: ["\x01\x02", "\x02\x03", "\x03\x04"] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.in",
    "expression": "getField(rules, 'in').size() > 0 && !(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in9bytesrepeated

not_in requires the field value to be not equal to any of the specified values. If the field value matches any of the specified values, an error message is generated.

message MyBytes {
// value must not in ["\x01\x02", "\x02\x03", "\x03\x04"]
optional bytes value = 1 [(buf.validate.field).bytes = { not_in: ["\x01\x02", "\x02\x03", "\x03\x04"] }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
ip10booloptional

ip ensures that the field value is a valid IP address (v4 or v6) in byte format. If the field value doesn't meet this rule, an error message is generated.

message MyBytes {
// must be a valid IP address
optional bytes value = 1 [(buf.validate.field).bytes.ip = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "bytes.ip",
      "message": "must be a valid IP address",
      "expression": "!rules.ip || this.size() == 0 || this.size() == 4 || this.size() == 16"
    },
    {
      "id": "bytes.ip_empty",
      "message": "value is empty, which is not a valid IP address",
      "expression": "!rules.ip || this.size() != 0"
    }
  ]
}
ipv411booloptional

ipv4 ensures that the field value is a valid IPv4 address in byte format. If the field value doesn't meet this rule, an error message is generated.

message MyBytes {
// must be a valid IPv4 address
optional bytes value = 1 [(buf.validate.field).bytes.ipv4 = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "bytes.ipv4",
      "message": "must be a valid IPv4 address",
      "expression": "!rules.ipv4 || this.size() == 0 || this.size() == 4"
    },
    {
      "id": "bytes.ipv4_empty",
      "message": "value is empty, which is not a valid IPv4 address",
      "expression": "!rules.ipv4 || this.size() != 0"
    }
  ]
}
ipv612booloptional

ipv6 ensures that the field value is a valid IPv6 address in byte format. If the field value doesn't meet this rule, an error message is generated.

message MyBytes {
// must be a valid IPv6 address
optional bytes value = 1 [(buf.validate.field).bytes.ipv6 = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "bytes.ipv6",
      "message": "must be a valid IPv6 address",
      "expression": "!rules.ipv6 || this.size() == 0 || this.size() == 16"
    },
    {
      "id": "bytes.ipv6_empty",
      "message": "value is empty, which is not a valid IPv6 address",
      "expression": "!rules.ipv6 || this.size() != 0"
    }
  ]
}
uuid15booloptional

uuid ensures that the field value encodes 128-bit UUID data as defined by RFC 4122. The field must contain exactly 16 bytes representing the UUID. If the field value isn't a valid UUID, an error message will be generated.

message MyBytes {
// must be a valid UUID
optional bytes value = 1 [(buf.validate.field).bytes.uuid = true];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "bytes.uuid",
      "message": "must be a valid UUID",
      "expression": "!rules.uuid || this.size() == 0 || this.size() == 16"
    },
    {
      "id": "bytes.uuid_empty",
      "message": "value is empty, which is not a valid UUID",
      "expression": "!rules.uuid || this.size() != 0"
    }
  ]
}
example14bytesrepeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyBytes {
bytes value = 1 [
(buf.validate.field).bytes.example = "\x01\x02",
(buf.validate.field).bytes.example = "\x02\x03"
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "bytes.example",
    "expression": "true"
  }
}

EnumRules describe the rules applied to enum values.

NameTagTypeLabelDescription
const1int32optional

const requires the field value to exactly match the specified enum value. If the field value doesn't match, an error message is generated.

enum MyEnum {
MY_ENUM_UNSPECIFIED = 0;
MY_ENUM_VALUE1 = 1;
MY_ENUM_VALUE2 = 2;
}

message MyMessage {
// The field `value` must be exactly MY_ENUM_VALUE1.
MyEnum value = 1 [(buf.validate.field).enum.const = 1];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "enum.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
defined_only2booloptional

defined_only requires the field value to be one of the defined values for this enum, failing on any undefined value.

enum MyEnum {
MY_ENUM_UNSPECIFIED = 0;
MY_ENUM_VALUE1 = 1;
MY_ENUM_VALUE2 = 2;
}

message MyMessage {
// The field `value` must be a defined value of MyEnum.
MyEnum value = 1 [(buf.validate.field).enum.defined_only = true];
}
in3int32repeated

in requires the field value to be equal to one of the specified enum values. If the field value doesn't match any of the specified values, an error message is generated.

enum MyEnum {
MY_ENUM_UNSPECIFIED = 0;
MY_ENUM_VALUE1 = 1;
MY_ENUM_VALUE2 = 2;
}

message MyMessage {
// The field `value` must be equal to one of the specified values.
MyEnum value = 1 [(buf.validate.field).enum = { in: [1, 2]}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "enum.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in4int32repeated

not_in requires the field value to be not equal to any of the specified enum values. If the field value matches one of the specified values, an error message is generated.

enum MyEnum {
MY_ENUM_UNSPECIFIED = 0;
MY_ENUM_VALUE1 = 1;
MY_ENUM_VALUE2 = 2;
}

message MyMessage {
// The field `value` must not be equal to any of the specified values.
MyEnum value = 1 [(buf.validate.field).enum = { not_in: [1, 2]}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "enum.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example5int32repeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

enum MyEnum {
MY_ENUM_UNSPECIFIED = 0;
MY_ENUM_VALUE1 = 1;
MY_ENUM_VALUE2 = 2;
}

message MyMessage {
MyEnum value = 1 [
(buf.validate.field).enum.example = 1,
(buf.validate.field).enum.example = 2
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "enum.example",
    "expression": "true"
  }
}

RepeatedRules describe the rules applied to repeated values.

NameTagTypeLabelDescription
min_items1uint64optional

min_items requires that this field must contain at least the specified minimum number of items.

Note that min_items = 1 is equivalent to setting a field as required.

message MyRepeated {
// value must contain at least  2 items
repeated string value = 1 [(buf.validate.field).repeated.min_items = 2];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "repeated.min_items",
    "expression": "uint(this.size()) < rules.min_items ? 'must contain at least %d item(s)'.format([rules.min_items]) : ''"
  }
}
max_items2uint64optional

max_items denotes that this field must not exceed a certain number of items as the upper limit. If the field contains more items than specified, an error message will be generated, requiring the field to maintain no more than the specified number of items.

message MyRepeated {
// value must contain no more than 3 item(s)
repeated string value = 1 [(buf.validate.field).repeated.max_items = 3];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "repeated.max_items",
    "expression": "uint(this.size()) > rules.max_items ? 'must contain no more than %s item(s)'.format([rules.max_items]) : ''"
  }
}
unique3booloptional

unique indicates that all elements in this field must be unique. This rule is strictly applicable to scalar and enum types, with message types not being supported.

message MyRepeated {
// repeated value must contain unique items
repeated string value = 1 [(buf.validate.field).repeated.unique = true];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "repeated.unique",
    "message": "repeated value must contain unique items",
    "expression": "!rules.unique || this.unique()"
  }
}
items4FieldRulesoptional

items details the rules to be applied to each item in the field. Even for repeated message fields, validation is executed against each item unless ignore is specified.

message MyRepeated {
// The items in the field `value` must follow the specified rules.
repeated string value = 1 [(buf.validate.field).repeated.items = {
string: {
min_len: 3
max_len: 10
}
}];
}

Note that the required rule does not apply. Repeated items cannot be unset.

MapRules describe the rules applied to map values.

NameTagTypeLabelDescription
min_pairs1uint64optional

Specifies the minimum number of key-value pairs allowed. If the field has fewer key-value pairs than specified, an error message is generated.

message MyMap {
// The field `value` must have at least 2 key-value pairs.
map value = 1 [(buf.validate.field).map.min_pairs = 2];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "map.min_pairs",
    "expression": "uint(this.size()) < rules.min_pairs ? 'map must be at least %d entries'.format([rules.min_pairs]) : ''"
  }
}
max_pairs2uint64optional

Specifies the maximum number of key-value pairs allowed. If the field has more key-value pairs than specified, an error message is generated.

message MyMap {
// The field `value` must have at most 3 key-value pairs.
map value = 1 [(buf.validate.field).map.max_pairs = 3];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "map.max_pairs",
    "expression": "uint(this.size()) > rules.max_pairs ? 'map must be at most %d entries'.format([rules.max_pairs]) : ''"
  }
}
keys4FieldRulesoptional

Specifies the rules to be applied to each key in the field.

message MyMap {
// The keys in the field `value` must follow the specified rules.
map value = 1 [(buf.validate.field).map.keys = {
string: {
min_len: 3
max_len: 10
}
}];
}

Note that the required rule does not apply. Map keys cannot be unset.

values5FieldRulesoptional

Specifies the rules to be applied to the value of each key in the field. Message values will still have their validations evaluated unless ignore is specified.

message MyMap {
// The values in the field `value` must follow the specified rules.
map value = 1 [(buf.validate.field).map.values = {
string: {
min_len: 5
max_len: 20
}
}];
}

Note that the required rule does not apply. Map values cannot be unset.

AnyRules describe rules applied exclusively to the google.protobuf.Any well-known type.

NameTagTypeLabelDescription
in2stringrepeated

in requires the field's type_url to be equal to one of the specified values. If it doesn't match any of the specified values, an error message is generated.

message MyAny {
//  The `value` field must have a `type_url` equal to one of the specified values.
google.protobuf.Any value = 1 [(buf.validate.field).any = {
in: ["type.googleapis.com/MyType1", "type.googleapis.com/MyType2"]
}];
}
not_in3stringrepeated

not_in requires the field's type_url to be not equal to any of the specified values. If it matches any of the specified values, an error message is generated.

message MyAny {
//  The `value` field must not have a `type_url` equal to any of the specified values.
google.protobuf.Any value = 1 [(buf.validate.field).any = {
not_in: ["type.googleapis.com/ForbiddenType1", "type.googleapis.com/ForbiddenType2"]
}];
}

DurationRules describe the rules applied exclusively to the google.protobuf.Duration well-known type.

NameTagTypeLabelDescription
const2google.protobuf.Durationoptional

const dictates that the field must match the specified value of the google.protobuf.Duration type exactly. If the field's value deviates from the specified value, an error message will be generated.

message MyDuration {
// value must equal 5s
google.protobuf.Duration value = 1 [(buf.validate.field).duration.const = { seconds: 5 }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "duration.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt3google.protobuf.Durationoptional

lt stipulates that the field must be less than the specified value of the google.protobuf.Duration type, exclusive. If the field's value is greater than or equal to the specified value, an error message will be generated.

message MyDuration {
// must be less than 5s
google.protobuf.Duration value = 1 [(buf.validate.field).duration.lt = { seconds: 5 }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "duration.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte4google.protobuf.Durationoptional

lte indicates that the field must be less than or equal to the specified value of the google.protobuf.Duration type, inclusive. If the field's value is greater than the specified value, an error message will be generated.

message MyDuration {
// must be less than or equal to 10s
google.protobuf.Duration value = 1 [(buf.validate.field).duration.lte = { seconds: 10 }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "duration.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
gt5google.protobuf.Durationoptional

gt requires the duration field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyDuration {
// duration must be greater than 5s [duration.gt]
google.protobuf.Duration value = 1 [(buf.validate.field).duration.gt = { seconds: 5 }];

// duration must be greater than 5s and less than 10s [duration.gt_lt]
google.protobuf.Duration another_value = 2 [(buf.validate.field).duration = { gt: { seconds: 5 }, lt: { seconds: 10 } }];

// duration must be greater than 10s or less than 5s [duration.gt_lt_exclusive]
google.protobuf.Duration other_value = 3 [(buf.validate.field).duration = { gt: { seconds: 10 }, lt: { seconds: 5 } }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "duration.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "duration.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "duration.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "duration.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "duration.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte6google.protobuf.Durationoptional

gte requires the duration field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyDuration {
// duration must be greater than or equal to 5s [duration.gte]
google.protobuf.Duration value = 1 [(buf.validate.field).duration.gte = { seconds: 5 }];

// duration must be greater than or equal to 5s and less than 10s [duration.gte_lt]
google.protobuf.Duration another_value = 2 [(buf.validate.field).duration = { gte: { seconds: 5 }, lt: { seconds: 10 } }];

// duration must be greater than or equal to 10s or less than 5s [duration.gte_lt_exclusive]
google.protobuf.Duration other_value = 3 [(buf.validate.field).duration = { gte: { seconds: 10 }, lt: { seconds: 5 } }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "duration.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "duration.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "duration.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "duration.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "duration.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
in7google.protobuf.Durationrepeated

in asserts that the field must be equal to one of the specified values of the google.protobuf.Duration type. If the field's value doesn't correspond to any of the specified values, an error message will be generated.

message MyDuration {
// must be in list [1s, 2s, 3s]
google.protobuf.Duration value = 1 [(buf.validate.field).duration = {
in: [{ seconds: 1 }, { seconds: 2 }, { seconds: 3 }]
}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "duration.in",
    "expression": "!(this in getField(rules, 'in')) ? 'must be in list %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in8google.protobuf.Durationrepeated

not_in denotes that the field must not be equal to any of the specified values of the google.protobuf.Duration type. If the field's value matches any of these values, an error message will be generated.

message MyDuration {
// value must not be in list [1s, 2s, 3s]
google.protobuf.Duration value = 1 [(buf.validate.field).duration = {
not_in: [{ seconds: 1 }, { seconds: 2 }, { seconds: 3 }]
}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "duration.not_in",
    "expression": "this in rules.not_in ? 'must not be in list %s'.format([rules.not_in]) : ''"
  }
}
example9google.protobuf.Durationrepeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyDuration {
google.protobuf.Duration value = 1 [
(buf.validate.field).duration.example = { seconds: 1 },
(buf.validate.field).duration.example = { seconds: 2 }
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "duration.example",
    "expression": "true"
  }
}

FieldMaskRules describe rules applied exclusively to the google.protobuf.FieldMask well-known type.

NameTagTypeLabelDescription
const1google.protobuf.FieldMaskoptional

const dictates that the field must match the specified value of the google.protobuf.FieldMask type exactly. If the field's value deviates from the specified value, an error message will be generated.

message MyFieldMask {
// value must equal ["a"]
google.protobuf.FieldMask value = 1 [(buf.validate.field).field_mask.const = {
paths: ["a"]
}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "field_mask.const",
    "expression": "this.paths != getField(rules, 'const').paths ? 'must equal paths %s'.format([getField(rules, 'const').paths]) : ''"
  }
}
in2stringrepeated

in requires the field value to only contain paths matching specified values or their subpaths. If any of the field value's paths doesn't match the rule, an error message is generated. See: https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask

message MyFieldMask {
//  The `value` FieldMask must only contain paths listed in `in`.
google.protobuf.FieldMask value = 1 [(buf.validate.field).field_mask = {
in: ["a", "b", "c.a"]
}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "field_mask.in",
    "expression": "!this.paths.all(p, p in getField(rules, 'in') || getField(rules, 'in').exists(f, p.startsWith(f+'.'))) ? 'must only contain paths in %s'.format([getField(rules, 'in')]) : ''"
  }
}
not_in3stringrepeated

not_in requires the field value to not contain paths matching specified values or their subpaths. If any of the field value's paths matches the rule, an error message is generated. See: https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask

message MyFieldMask {
//  The `value` FieldMask shall not contain paths listed in `not_in`.
google.protobuf.FieldMask value = 1 [(buf.validate.field).field_mask = {
not_in: ["forbidden", "immutable", "c.a"]
}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "field_mask.not_in",
    "expression": "!this.paths.all(p, !(p in getField(rules, 'not_in') || getField(rules, 'not_in').exists(f, p.startsWith(f+'.')))) ? 'must not contain any paths in %s'.format([getField(rules, 'not_in')]) : ''"
  }
}
example4google.protobuf.FieldMaskrepeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyFieldMask {
google.protobuf.FieldMask value = 1 [
(buf.validate.field).field_mask.example = { paths: ["a", "b"] },
(buf.validate.field).field_mask.example = { paths: ["c.a", "d"] }
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "field_mask.example",
    "expression": "true"
  }
}

TimestampRules describe the rules applied exclusively to the google.protobuf.Timestamp well-known type.

NameTagTypeLabelDescription
const2google.protobuf.Timestampoptional

const dictates that this field, of the google.protobuf.Timestamp type, must exactly match the specified value. If the field value doesn't correspond to the specified timestamp, an error message will be generated.

message MyTimestamp {
// value must equal 2023-05-03T10:00:00Z
google.protobuf.Timestamp created_at = 1 [(buf.validate.field).timestamp.const = {seconds: 1727998800}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "timestamp.const",
    "expression": "this != getField(rules, 'const') ? 'must equal %s'.format([getField(rules, 'const')]) : ''"
  }
}
lt3google.protobuf.Timestampoptional

lt requires the timestamp field value to be less than the specified value (field < value). If the field value doesn't meet the required conditions, an error message is generated.

message MyTimestamp {
// timestamp must be less than '2023-01-01T00:00:00Z' [timestamp.lt]
google.protobuf.Timestamp value = 1 [(buf.validate.field).timestamp.lt = { seconds: 1672444800 }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "timestamp.lt",
    "expression": "!has(rules.gte) && !has(rules.gt) && this >= rules.lt? 'must be less than %s'.format([rules.lt]) : ''"
  }
}
lte4google.protobuf.Timestampoptional

lte requires the timestamp field value to be less than or equal to the specified value (field <= value). If the field value doesn't meet the required conditions, an error message is generated.

message MyTimestamp {
// timestamp must be less than or equal to '2023-05-14T00:00:00Z' [timestamp.lte]
google.protobuf.Timestamp value = 1 [(buf.validate.field).timestamp.lte = { seconds: 1678867200 }];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "timestamp.lte",
    "expression": "!has(rules.gte) && !has(rules.gt) && this > rules.lte? 'must be less than or equal to %s'.format([rules.lte]) : ''"
  }
}
lt_now7booloptional

lt_now specifies that this field, of the google.protobuf.Timestamp type, must be less than the current time. lt_now can only be used with the within rule.

message MyTimestamp {
// must be less than now
google.protobuf.Timestamp created_at = 1 [(buf.validate.field).timestamp.lt_now = true];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "timestamp.lt_now",
    "expression": "(rules.lt_now && this > now) ? 'must be less than now' : ''"
  }
}
gt5google.protobuf.Timestampoptional

gt requires the timestamp field value to be greater than the specified value (exclusive). If the value of gt is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyTimestamp {
// timestamp must be greater than '2023-01-01T00:00:00Z' [timestamp.gt]
google.protobuf.Timestamp value = 1 [(buf.validate.field).timestamp.gt = { seconds: 1672444800 }];

// timestamp must be greater than '2023-01-01T00:00:00Z' and less than '2023-01-02T00:00:00Z' [timestamp.gt_lt]
google.protobuf.Timestamp another_value = 2 [(buf.validate.field).timestamp = { gt: { seconds: 1672444800 }, lt: { seconds: 1672531200 } }];

// timestamp must be greater than '2023-01-02T00:00:00Z' or less than '2023-01-01T00:00:00Z' [timestamp.gt_lt_exclusive]
google.protobuf.Timestamp other_value = 3 [(buf.validate.field).timestamp = { gt: { seconds: 1672531200 }, lt: { seconds: 1672444800 } }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "timestamp.gt",
      "expression": "!has(rules.lt) && !has(rules.lte) && this <= rules.gt? 'must be greater than %s'.format([rules.gt]) : ''"
    },
    {
      "id": "timestamp.gt_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gt && (this >= rules.lt || this <= rules.gt)? 'must be greater than %s and less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "timestamp.gt_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gt && (rules.lt <= this && this <= rules.gt)? 'must be greater than %s or less than %s'.format([rules.gt, rules.lt]) : ''"
    },
    {
      "id": "timestamp.gt_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gt && (this > rules.lte || this <= rules.gt)? 'must be greater than %s and less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    },
    {
      "id": "timestamp.gt_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gt && (rules.lte < this && this <= rules.gt)? 'must be greater than %s or less than or equal to %s'.format([rules.gt, rules.lte]) : ''"
    }
  ]
}
gte6google.protobuf.Timestampoptional

gte requires the timestamp field value to be greater than or equal to the specified value (exclusive). If the value of gte is larger than a specified lt or lte, the range is reversed, and the field value must be outside the specified range. If the field value doesn't meet the required conditions, an error message is generated.

message MyTimestamp {
// timestamp must be greater than or equal to '2023-01-01T00:00:00Z' [timestamp.gte]
google.protobuf.Timestamp value = 1 [(buf.validate.field).timestamp.gte = { seconds: 1672444800 }];

// timestamp must be greater than or equal to '2023-01-01T00:00:00Z' and less than '2023-01-02T00:00:00Z' [timestamp.gte_lt]
google.protobuf.Timestamp another_value = 2 [(buf.validate.field).timestamp = { gte: { seconds: 1672444800 }, lt: { seconds: 1672531200 } }];

// timestamp must be greater than or equal to '2023-01-02T00:00:00Z' or less than '2023-01-01T00:00:00Z' [timestamp.gte_lt_exclusive]
google.protobuf.Timestamp other_value = 3 [(buf.validate.field).timestamp = { gte: { seconds: 1672531200 }, lt: { seconds: 1672444800 } }];
}
(buf.validate.predefined)
{
  "cel": [
    {
      "id": "timestamp.gte",
      "expression": "!has(rules.lt) && !has(rules.lte) && this < rules.gte? 'must be greater than or equal to %s'.format([rules.gte]) : ''"
    },
    {
      "id": "timestamp.gte_lt",
      "expression": "has(rules.lt) && rules.lt >= rules.gte && (this >= rules.lt || this < rules.gte)? 'must be greater than or equal to %s and less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "timestamp.gte_lt_exclusive",
      "expression": "has(rules.lt) && rules.lt < rules.gte && (rules.lt <= this && this < rules.gte)? 'must be greater than or equal to %s or less than %s'.format([rules.gte, rules.lt]) : ''"
    },
    {
      "id": "timestamp.gte_lte",
      "expression": "has(rules.lte) && rules.lte >= rules.gte && (this > rules.lte || this < rules.gte)? 'must be greater than or equal to %s and less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    },
    {
      "id": "timestamp.gte_lte_exclusive",
      "expression": "has(rules.lte) && rules.lte < rules.gte && (rules.lte < this && this < rules.gte)? 'must be greater than or equal to %s or less than or equal to %s'.format([rules.gte, rules.lte]) : ''"
    }
  ]
}
gt_now8booloptional

gt_now specifies that this field, of the google.protobuf.Timestamp type, must be greater than the current time. gt_now can only be used with the within rule.

message MyTimestamp {
// must be greater than now
google.protobuf.Timestamp created_at = 1 [(buf.validate.field).timestamp.gt_now = true];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "timestamp.gt_now",
    "expression": "(rules.gt_now && this < now) ? 'must be greater than now' : ''"
  }
}
within9google.protobuf.Durationoptional

within specifies that this field, of the google.protobuf.Timestamp type, must be within the specified duration of the current time. If the field value isn't within the duration, an error message is generated.

message MyTimestamp {
// must be within 1 hour of now
google.protobuf.Timestamp created_at = 1 [(buf.validate.field).timestamp.within = {seconds: 3600}];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "timestamp.within",
    "expression": "this < now-rules.within || this > now+rules.within ? 'must be within %s of now'.format([rules.within]) : ''"
  }
}
example10google.protobuf.Timestamprepeated

example specifies values that the field may have. These values SHOULD conform to other rules. example values will not impact validation but may be used as helpful guidance on how to populate the given field.

message MyTimestamp {
google.protobuf.Timestamp value = 1 [
(buf.validate.field).timestamp.example = { seconds: 1672444800 },
(buf.validate.field).timestamp.example = { seconds: 1672531200 }
];
}
(buf.validate.predefined)
{
  "cel": {
    "id": "timestamp.example",
    "expression": "true"
  }
}

Violations is a collection of Violation messages. This message type is returned by Protovalidate when a proto message fails to meet the requirements set by the Rule validation rules. Each individual violation is represented by a Violation message.

NameTagTypeLabelDescription
violations1Violationrepeated

violations is a repeated field that contains all the Violation messages corresponding to the violations detected.

Violation represents a single instance where a validation rule, expressed as a Rule, was not met. It provides information about the field that caused the violation, the specific rule that wasn't fulfilled, and a human-readable error message.

For example, consider the following message:

message User {
int32 age = 1 [(buf.validate.field).cel = {
id: "user.age",
expression: "this < 18 ? 'User must be at least 18 years old' : ''",
}];
}

It could produce the following violation:

{
"ruleId": "user.age",
"message": "User must be at least 18 years old",
"field": {
"elements": [
{
"fieldNumber": 1,
"fieldName": "age",
"fieldType": "TYPE_INT32"
}
]
},
"rule": {
"elements": [
{
"fieldNumber": 23,
"fieldName": "cel",
"fieldType": "TYPE_MESSAGE",
"index": "0"
}
]
}
}
NameTagTypeLabelDescription
field5FieldPathoptional

field is a machine-readable path to the field that failed validation. This could be a nested field, in which case the path will include all the parent fields leading to the actual field that caused the violation.

For example, consider the following message:

message Message {
bool a = 1 [(buf.validate.field).required = true];
}

It could produce the following violation:

violation {
field { element { field_number: 1, field_name: "a", field_type: 8 } }
...
}
rule6FieldPathoptional

rule is a machine-readable path that points to the specific rule that failed validation. This will be a nested field starting from the FieldRules of the field that failed validation. For custom rules, this will provide the path of the rule, e.g. cel[0].

For example, consider the following message:

message Message {
bool a = 1 [(buf.validate.field).required = true];
bool b = 2 [(buf.validate.field).cel = {
id: "custom_rule",
expression: "!this ? 'b must be true': ''"
}];
}

It could produce the following violations:

violation {
rule { element { field_number: 25, field_name: "required", field_type: 8 } }
...
}
violation {
rule { element { field_number: 23, field_name: "cel", field_type: 11, index: 0 } }
...
}
rule_id2stringoptional

rule_id is the unique identifier of the Rule that was not fulfilled. This is the same id that was specified in the Rule message, allowing easy tracing of which rule was violated.

message3stringoptional

message is a human-readable error message that describes the nature of the violation. This can be the default error message from the violated Rule, or it can be a custom message that gives more context about the violation.

for_key4booloptional

for_key indicates whether the violation was caused by a map key, rather than a value.

FieldPath provides a path to a nested protobuf field.

This message provides enough information to render a dotted field path even without protobuf descriptors. It also provides enough information to resolve a nested field through unknown wire data.

NameTagTypeLabelDescription
elements1FieldPathElementrepeated

elements contains each element of the path, starting from the root and recursing downward.

FieldPathElement provides enough information to nest through a single protobuf field.

If the selected field is a map or repeated field, the subscript value selects a specific element from it. A path that refers to a value nested under a map key or repeated field index will have a subscript value. The field_type field allows unambiguous resolution of a field even if descriptors are not available.

NameTagTypeLabelDescription
field_number1int32optional

field_number is the field number this path element refers to.

field_name2stringoptional

field_name contains the field name this path element refers to. This can be used to display a human-readable path even if the field number is unknown.

field_type3google.protobuf.FieldDescriptorProto.Typeoptional

field_type specifies the type of this field. When using reflection, this value is not needed.

This value is provided to make it possible to traverse unknown fields through wire data. When traversing wire data, be mindful of both packed1 and delimited2 encoding schemes.

N.B.: Although groups are deprecated, the corresponding delimited encoding scheme is not, and can be explicitly used in Protocol Buffers 2023 Edition.

key_type4google.protobuf.FieldDescriptorProto.Typeoptional

key_type specifies the map key type of this field. This value is useful when traversing unknown fields through wire data: specifically, it allows handling the differences between different integer encodings.

value_type5google.protobuf.FieldDescriptorProto.Typeoptional

value_type specifies map value type of this field. This is useful if you want to display a value inside unknown fields through wire data.

index6uint64optional

index specifies a 0-based index into a repeated field.

bool_key7booloptional

bool_key specifies a map key of type bool.

int_key8int64optional

int_key specifies a map key of type int32, int64, sint32, sint64, sfixed32 or sfixed64.

uint_key9uint64optional

uint_key specifies a map key of type uint32, uint64, fixed32 or fixed64.

string_key10stringoptional

string_key specifies a map key of type string.

Enums

Specifies how FieldRules.ignore behaves, depending on the field's value, and whether the field tracks presence.

NameValueDescription
IGNORE_UNSPECIFIED0

Ignore rules if the field tracks presence and is unset. This is the default behavior.

In proto3, only message fields, members of a Protobuf oneof, and fields with the optional label track presence. Consequently, the following fields are always validated, whether a value is set or not:

syntax="proto3";

message RulesApply {
string email = 1 [
(buf.validate.field).string.email = true
];
int32 age = 2 [
(buf.validate.field).int32.gt = 0
];
repeated string labels = 3 [
(buf.validate.field).repeated.min_items = 1
];
}

In contrast, the following fields track presence, and are only validated if a value is set:

syntax="proto3";

message RulesApplyIfSet {
optional string email = 1 [
(buf.validate.field).string.email = true
];
oneof ref {
string reference = 2 [
(buf.validate.field).string.uuid = true
];
string name = 3 [
(buf.validate.field).string.min_len = 4
];
}
SomeMessage msg = 4 [
(buf.validate.field).cel = {/* ... */}
];
}

To ensure that such a field is set, add the required rule.

To learn which fields track presence, see the Field Presence cheat sheet.

IGNORE_IF_ZERO_VALUE1

Ignore rules if the field is unset, or set to the zero value.

The zero value depends on the field type:

  • For strings, the zero value is the empty string.
  • For bytes, the zero value is empty bytes.
  • For bool, the zero value is false.
  • For numeric types, the zero value is zero.
  • For enums, the zero value is the first defined enum value.
  • For repeated fields, the zero is an empty list.
  • For map fields, the zero is an empty map.
  • For message fields, absence of the message (typically a null-value) is considered zero value.

For fields that track presence (e.g. adding the optional label in proto3), this a no-op and behavior is the same as the default IGNORE_UNSPECIFIED.

IGNORE_ALWAYS3

Always ignore rules, including the required rule.

This is useful for ignoring the rules of a referenced message, or to temporarily ignore rules during development.

message MyMessage {
// The field's rules will always be ignored, including any validations
// on value's fields.
MyOtherMessage value = 1 [
(buf.validate.field).ignore = IGNORE_ALWAYS
];
}

KnownRegex contains some well-known patterns.

NameValueDescription
KNOWN_REGEX_UNSPECIFIED0
KNOWN_REGEX_HTTP_HEADER_NAME1

HTTP header name as defined by RFC 7230.

KNOWN_REGEX_HTTP_HEADER_VALUE2

HTTP header value as defined by RFC 7230.

Extensions

Rules specify the validations to be performed on this message. By default, no validation is performed against a message.

Extends google.protobuf.MessageOptions

optional MessageRules message = 1159;

Rules specify the validations to be performed on this oneof. By default, no validation is performed against a oneof.

Extends google.protobuf.OneofOptions

optional OneofRules oneof = 1159;

Rules specify the validations to be performed on this field. By default, no validation is performed against a field.

Extends google.protobuf.FieldOptions

optional FieldRules field = 1159;

Specifies predefined rules. When extending a standard rule message, this adds additional CEL expressions that apply when the extension is used.

extend buf.validate.Int32Rules {
bool is_zero = 1001 [(buf.validate.predefined).cel = {
id: "int32.is_zero",
message: "must be zero",
expression: "!rule || this == 0",
}];
}

message Foo {
int32 reserved = 1 [(buf.validate.field).int32.(is_zero) = true];
}

Extends google.protobuf.FieldOptions

optional PredefinedRules predefined = 1160;