protovalidate-skills

Comprehensive knowledge base for buf.validate/protovalidate - Protocol Buffer validation library. Use for adding validation rules to proto fields, writing CEL expressions, custom error messages, and framework integration.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "protovalidate-skills" with this command: npx skills add lwx-cloud/protovalidate-skills/lwx-cloud-protovalidate-skills-protovalidate-skills

Protovalidate Skills for AI Agents

This skill provides comprehensive knowledge about protovalidate, the next-generation Protocol Buffer validation library from Buf. It replaces the deprecated protoc-gen-validate.

Target When

Invoke this skill when:

  • Defining proto validation rules: Adding constraints to .proto files
  • Custom validation: Writing CEL expressions for complex validation logic
  • Error handling: Implementing custom error messages
  • Framework integration: Using protovalidate with Kratos, go-zero, or other frameworks
  • Migration: Upgrading from protoc-gen-validate to protovalidate
  • Debugging: Troubleshooting validation errors

Quick Reference

Basic Syntax

syntax = "proto3";

package my.package;

import "buf/validate/validate.proto";

message User {
  // String validation
  string username = 1 [(buf.validate.field).string = {
    min_len: 3,
    max_len: 32,
    pattern: "^[a-zA-Z0-9_]+$"
  }];

  // Integer validation
  int64 age = 2 [(buf.validate.field).int64 = {gte: 0, lte: 150}];

  // Email validation
  string email = 3 [(buf.validate.field).string.email = true];

  // Custom CEL validation with Chinese error message
  string mobile = 4 [(buf.validate.field).cel = {
    id: "mobile_format",
    message: "手机号格式错误",
    expression: "this.matches('^1[3-9][0-9]{9}$')"
  }];
}

Import Path

// Buf CLI managed mode
import "buf/validate/validate.proto";

// Option extension
option (buf.validate.field) = { ... };
option (buf.validate.message) = { ... };
option (buf.validate.oneof) = { ... };

Knowledge Structure

Load specific guides as needed:

Field Type Rules

FileWhen to Load
references/string-rules.mdString validation (length, pattern, email, IP, UUID, etc.)
references/number-rules.mdNumeric validation (int32, int64, float, double, etc.)
references/complex-rules.mdComplex types (repeated, map, enum, bytes, etc.)
references/message-rules.mdMessage-level validation, oneof rules

CEL & Custom Rules

FileWhen to Load
references/cel-expressions.mdCEL syntax, functions, cross-field validation
references/custom-errors.mdCustom error messages, localization

Examples

FileWhen to Load
examples/common-patterns.mdCommon validation patterns
examples/chinese-validation.mdChinese-specific validation (mobile, ID card, etc.)

Framework Integrations

FileWhen to Load
integrations/kratos.mdGo-Kratos framework integration

Other framework integrations (go-zero, Spring Boot, etc.) can be added to integrations/ directory.

Field Types Overview

Scalar Types

Proto TypeRules TypeExample
stringStringRules[(buf.validate.field).string.min_len = 1]
int32Int32Rules[(buf.validate.field).int32.gt = 0]
int64Int64Rules[(buf.validate.field).int64.gte = 1]
uint32UInt32Rules[(buf.validate.field).uint32.lte = 100]
uint64UInt64Rules[(buf.validate.field).uint64.gt = 0]
floatFloatRules[(buf.validate.field).float.gte = 0.0]
doubleDoubleRules[(buf.validate.field).double.lt = 100.0]
boolBoolRules[(buf.validate.field).bool.const = true]
bytesBytesRules[(buf.validate.field).bytes.min_len = 1]

Complex Types

Proto TypeRules TypeExample
enumEnumRules[(buf.validate.field).enum.defined_only = true]
repeatedRepeatedRules[(buf.validate.field).repeated.min_items = 1]
mapMapRules[(buf.validate.field).map.min_pairs = 1]
messageMessageRules[(buf.validate.field).required = true]

Common Validation Rules

String Rules

RuleDescriptionExample
min_lenMinimum character count (Unicode)min_len: 3
max_lenMaximum character count (Unicode)max_len: 32
lenExact character countlen: 11
min_bytesMinimum byte countmin_bytes: 1
max_bytesMaximum byte countmax_bytes: 255
patternRE2 regex patternpattern: "^[a-z]+$"
prefixMust start withprefix: "https://"
suffixMust end withsuffix: ".com"
containsMust contain substringcontains: "@"
not_containsMust not containnot_contains: "spam"
inMust be one of valuesin: ["a", "b", "c"]
not_inMust not be one ofnot_in: ["admin", "root"]
emailValid email formatemail: true
hostnameValid hostnamehostname: true
ipValid IP (v4/v6)ip: true
ipv4Valid IPv4 onlyipv4: true
ipv6Valid IPv6 onlyipv6: true
uriValid URIuri: true
uuidValid UUIDuuid: true
constMust equal exactlyconst: "fixed"

Numeric Rules

RuleDescriptionExample
constMust equal exactlyconst: 42
ltLess than (exclusive)lt: 100
lteLess than or equallte: 100
gtGreater than (exclusive)gt: 0
gteGreater than or equalgte: 1
inMust be one of valuesin: [1, 2, 3]
not_inMust not be one ofnot_in: [0, -1]

Float/Double Only

RuleDescriptionExample
finiteMust be finite (not NaN/Inf)finite: true

Ignore Options

// Ignore if field is unset or zero value
string optional_field = 1 [
  (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE,
  (buf.validate.field).string.email = true
];

// Always ignore validation (useful for development)
string dev_field = 2 [
  (buf.validate.field).ignore = IGNORE_ALWAYS
];

Required Fields

message Request {
  // For fields with presence tracking (optional, message types)
  optional string name = 1 [(buf.validate.field).required = true];

  // Message type - required means must be set
  User user = 2 [(buf.validate.field).required = true];
}

CEL Expressions

Basic CEL Syntax

message Example {
  // Field-level CEL
  int32 value = 1 [(buf.validate.field).cel = {
    id: "value_positive",
    message: "value must be positive",
    expression: "this > 0"
  }];

  // Simplified CEL (id and message derived from expression)
  int32 value2 = 2 [(buf.validate.field).cel_expression = "this > 0"];

  // Message-level CEL for cross-field validation
  option (buf.validate.message).cel = {
    id: "password_match",
    message: "passwords must match",
    expression: "this.password == this.confirm_password"
  };

  string password = 1;
  string confirm_password = 2;
}

CEL Functions

FunctionDescriptionExample
size()String/repeated/map sizesize(this) <= 32
matches()Regex match (RE2)this.matches('^[a-z]+$')
startsWith()Prefix checkthis.startsWith('http')
endsWith()Suffix checkthis.endsWith('.com')
contains()Substring checkthis.contains('@')
isEmail()Email validationthis.isEmail()
isHostname()Hostname validationthis.isHostname()
isIp()IP validationthis.isIp()
isIpv4()IPv4 validationthis.isIpv4()
isIpv6()IPv6 validationthis.isIpv6()
isUri()URI validationthis.isUri()
isUuid()UUID validationthis.isUuid()
has()Field presence checkhas(this.field)
getType()Get field typegetType(this)

CEL for Chinese Validation

// Chinese mobile phone
string mobile = 1 [(buf.validate.field).cel = {
  id: "mobile_format",
  message: "手机号格式错误,必须为11位有效手机号",
  expression: "this.matches('^1[3-9][0-9]{9}$')"
}];

// Chinese ID card (18 digits)
string id_card = 2 [(buf.validate.field).cel = {
  id: "id_card_format",
  message: "身份证号格式错误",
  expression: "this.matches('^[1-9][0-9]{5}(19|20)[0-9]{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9Xx]$')"
}];

Best Practices

Always Follow

  • Use buf.validate.field for field-level rules
  • Use buf.validate.message for cross-field validation
  • Provide meaningful id and message for CEL rules
  • Use IGNORE_IF_ZERO_VALUE for optional fields
  • Test validation rules with edge cases

Never Do

  • Use protoc-gen-validate syntax (deprecated)
  • Mix buf.validate with validate imports
  • Use \d in regex patterns (use [0-9] instead)
  • Reference other fields in field-level CEL (use message-level instead)
  • Modify generated .pb.go files

Framework Integration

Kratos Middleware

// pkg/middleware/validate.go
package middleware

import (
    "context"
    stderrors "errors"
    "buf.build/go/protovalidate"
    "github.com/go-kratos/kratos/v2/middleware"
    "google.golang.org/protobuf/proto"
    v1 "your-project/api/v1"
)

var validator protovalidate.Validator

func init() {
    var err error
    validator, err = protovalidate.New()
    if err != nil {
        panic(err)
    }
}

func Validator() middleware.Middleware {
    return func(handler middleware.Handler) middleware.Handler {
        return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
            if msg, ok := req.(proto.Message); ok {
                if err := validator.Validate(msg); err != nil {
                    var valErr *protovalidate.ValidationError
                    if stderrors.As(err, &valErr) {
                        violations := valErr.Violations
                        if len(violations) > 0 && violations[0].Proto.GetMessage() != "" {
                            return nil, v1.ErrorBadRequest(violations[0].Proto.GetMessage())
                        }
                    }
                    return nil, v1.ErrorBadRequest(err.Error())
                }
            }
            return handler(ctx, req)
        }
    }
}

buf.gen.yaml Configuration

# v2 format
version: v2
managed:
  enabled: true
  disable:
    - file_option: go_package_prefix
      module: buf.build/bufbuild/protovalidate
plugins:
  - local: protoc-gen-go
    out: .
    opt:
      - paths=source_relative
  - local: protoc-gen-go-grpc
    out: .
    opt:
      - paths=source_relative
  - local: protoc-gen-go-http
    out: .
    opt:
      - paths=source_relative

Resources


Quick invocation: Use /protovalidate-skills or ask "How do I validate [field type] with protovalidate?"

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

kratos-skills

No summary provided by upstream source.

Repository SourceNeeds Review
Research

learn-anything-in-one-hour

Teach users any new skill/knowledge X in ~1 hour using a fixed 4-step workflow optimized for complete beginners, focusing on 80/20 rule for maximum value in minimum time. Triggers when user asks to learn something new quickly, or mentions "learn X in one hour".

Archived SourceRecently Updated
Research

X/Twitter Research

# X/Twitter Research Skill

Archived SourceRecently Updated