Author: @mcy
Approved: 2022-11-15
A versioning mechanism for descriptors that ensures old runtimes do not load descriptors that are “too new.”
Suppose we decide to add a novel definition like
const int32 MY_CONSTANT = 42;
to the Protobuf language. This would entail a descriptor change to track the values of constants, but they would not be loaded properly by older runtimes. This document describes an addition to descriptor.proto
that prevents this version mismatch issue.
Protobuf Editions intends to add the concept of an edition to Protobuf, which will be an approximately-annually incrementing value. Because of their annual nature, and because runtimes need to be updated to handle new features they implement regardless, we can use them as a poison pill for old runtimes that try to load descriptors that are “too new.”
We propose adding a new field to FileDescriptorProto
:
optional string minimum_required_edition = ...;
This field would exist alongside the edition
field, and would have the following semantics:
Every Protobuf runtime implementation must specify the newest edition whose constructs it can handle (at a particular rev of that implementation). If that edition is less than minimum_required_edition
, loading the descriptor must fail.
“Less than” is defined per the edition total order given in Life of an Edition. To restate it, it is the following algorithm:
def edition_less_than(a, b): parts_a = a.split(".") parts_b = b.split(".") for i in range(0, min(len(parts_a), len(parts_b))): if int(parts_a[i]) < int(parts_b[i]): return True return len(a) < len(b)
protoc
should keep track of which constructions require which minimum edition. For example, if constants are introduced in edition 2025, but they are not present in a file, protoc
should not require that runtimes understand constants by picking a lower edition, like 2023 (assuming no other construct requires a higher edition).
In particular, the following changes should keep the minimum edition constant, with all other things unchanged:
“Epochs for descriptor.proto
” (not available externally) describes a potential issue with bootstrapping. It is not the case here: minimum edition is only incremented once a particular file uses a new feature. Since descriptor.proto
and other schemas used by protoc
and the backends would not use new features immediately, introducing a new feature does not immediately stop the compiler from being able to compile itself.
Schema producers should consider changes to their schemas that increase the minimum required edition to be breaking changes, since it will stop compiled descriptors from being loaded at runtime.
We recommend adding the aforementioned minimum required edition field, along with the semantics it entails. This logic should be implemented entirely in the protoc frontend.
Rather than using the editions value, use some other version number. This number would be incremented rarely (3-5 year horizon). This is the approach proposed in “Epochs for descriptor.proto
.”
The proto compiler should not guarantee that the minimum required edition is as small as it could possibly be.
descriptor.proto
.”