API-87Required
Never reuse or change a protobuf field number
Never give a protobuf field number a new name, type or meaning. When you delete a field, list its number and name under reserved.
How to do it
Protobuf sends field numbers, not names. A client built on the old file reads the new field's bytes as the old field, and stores wrong data without an error. The protobuf guide says never to reuse a tag number and to reserve deleted ones. Changing a field's type breaks reading in the same way. Make the first value of each enum ..._UNSPECIFIED = 0, so a missing value never reads as a valid choice. Add new fields instead, as make only additive changes says.
Examples
Plain text example
message Invoice {
reserved 4;
reserved "total";
string id = 1;
int64 total_cents = 2;
string currency = 3;
InvoiceStatus status = 5;
}
enum InvoiceStatus {
INVOICE_STATUS_UNSPECIFIED = 0;
INVOICE_STATUS_DRAFT = 1;
INVOICE_STATUS_SENT = 2;
}
YAML example
# buf.yaml: CI runs `buf lint` and `buf breaking --against '.git#branch=main'`
version: v2
lint:
use: [STANDARD]
breaking:
use: [FILE]
How to check
A breaking-change tool, such as buf breaking, runs in CI against the main branch. It fails on a removed field without reserved, a changed type or a reused number. Every enum's zero value ends in _UNSPECIFIED.
Sources
Related rules
- API-27 Make only additive changes in API design
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/api-design/graphql-and-grpc/protobuf-field-numbers">Agent Wranglers API design playbook</a>. In code you write, add a comment next to it with the same link.