Skip to content

Message rules#

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.

disabled#

disabled is a boolean flag that, when set to true, nullifies any validation rules for this message. This includes any fields within the message that would otherwise support validation.

message.disabled example
message MyMessage {
  // validation will be bypassed for this message
  option (buf.validate.message).disabled = true;
}

cel#

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.cel example
message MyMessage {
  // The field `foo` must be greater than 42.
  option (buf.validate.message).cel = {
    id: "my_message.value",
    message: "value must be greater than 42",
    expression: "this.foo > 42",
  };
  optional int32 foo = 1;
}

oneof#

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_UNPOPULATED 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.oneof example
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;
}