News Announcements for Version 26.x

Changes announced for Protocol Buffers version 26.x.

The following announcements are specific to Version 26.x. For information presented chronologically, see News.

General Changes

JSON Formatter Option Changes

Starting in the 26.x line, the JSON formatter option to print default-valued fields is replaced with a fixed way to handle proto2 and proto3 optional fields consistently.

  • Java: includingDefaultValueFields() is replaced with alwaysPrintFieldsWithNoPresence().
  • C++: always_print_default_values is replaced with always_print_fields_with_no_presence=True.
  • Py: including_default_value_fields=True is replaced with always_print_fields_with_no_presence=True.

The new flag behaves identically to the old flag on proto3 messages, but no longer applies to proto2 optional fields. The old flags applied to proto2 optional fields but not proto3 optional fields.

Poison Pilling Gencode / Runtime Mismatches

Per our Cross-Version Runtime Guarantees, Protobuf does not support mixing generated code and runtimes across major version boundaries, or mixing generated code from a newer version of protoc with older runtimes within a single major runtime version. We plan to introduce “poison pills” to detect and enforce these disallowed mismatches.

This is not considered a breaking change since this simply adds enforcement of existing policies, but may require users to update their generated code.

C++ Breaking Changes

In v26, we are planning a major version bump for C++ as per our breaking changes policy and version support policy.

The following sections outline the set of breaking changes that we plan to include in the 26.0 release of protocol buffers. Note that plans can and do change. These are potential breaking changes to be aware of, but they may not happen in this particular release, or they may not happen at all.

Remove deprecated clear APIs on repeated fields

The following deprecated methods are removed:

  • RepeatedPtrField::ReleaseCleared()
  • RepeatedPtrField::ClearedCount()
  • RepeatedPtrField::AddCleared()

Remove C++ legacy syntax descriptor APIs

With the release of editions, syntax is no longer supported for business logic. Instead, use the various feature helpers defined in descriptor.h to query more targeted behaviors, such as has_presence, to query features in C++.

Remove deprecated syntax accessor

We plan to remove the deprecated syntax accessor, FileDescriptor::Syntax, in v26. We recommend using the getters from FileDescriptor::edition instead.

Remove deprecated SupportsUnknownEnumValues method

The SupportsUnknownEnumValues method was deprecated in March, 2023. We plan to remove it in v26.

Remove std::string error collector overrides

We are planning to remove the deprecated std::string methods in error collectors.

Java Breaking Changes

In v26, we are planning a major version bump for Java per our breaking changes policy and version support policy.

The following sections outline the set of breaking changes that we plan to include in the 26.0 release of protocol buffers. Note that plans can and do change. These are potential breaking changes to be aware of, but they may not happen in this particular release, or they may not happen at all.

Breaking Compatibility with Old Generated Code

v26.x will break compatibility with generated code from older major versions. Users should regenerate old generated code to be from the same version.

For example, GeneratedMessageV3, which was originally introduced for backwards compatibility with generated code from v2.x.x against v3.x.x runtime, will be renamed to GeneratedMessage. Runtimes will be updated to support Editions, which will not be compatible with old generated code.

This is in accordance with our existing Cross-Version Runtime Guarantees and is a breaking change.

Removing Deprecated Methods/Variables

v26.x will remove access to deprecated methods and variables. These will generally have already been marked @Deprecated in a previous release.

This will remove access to the following non-exhaustive list:

  • Descriptor syntax APIs, which should be replaced with corresponding feature accessors (such as FieldDescriptor.hasPresence(), EnumDescriptor.isClosed())

  • TextFormat print methods, which should be replaced by corresponding TextFormat.printer() methods.

  • PARSER variable, which should be replaced by the parser() method.

  • Runtime methods for old v2.x.x gencode compatibility. This is no longer supported, as per our Cross Version Runtime Guarantees.

More details will be available in the corresponding release notes.

PHP Breaking Changes

The following changes are planned for the 26.x line:

  • Validate UTF-8 for string fields in setters.
  • Remove generic services. (commit 40ad3fa)

Python Breaking Changes

In v26, we are planning a major version bump for Python as per our breaking changes policy and version support policy.

The following changes are planned for the 26.x line:

  • Make str(msg) escape any invalid UTF-8 in string fields.
  • Make text_format.MessageToString() default to outputting raw UTF-8, while escaping any invalid UTF-8 sequences.
  • Fix timestamp bounds (commit 1250d5f)

Removing Deprecated APIs

In the 26.x release, the following deprecated APIs will be removed:

Rejecting Extend Repeated Field with None Iterable

Starting in the 26.x release, extending repeated fields with a None iterable will be rejected (it will raise a TypeError). For example, m.repeated_int32.extend(None) will be rejected.

Removing RegisterExtension in message class

Starting in the 26.x release, RegisterExtension will be removed. You can access extensions in Python using the Extensions property on message objects.

This affects both pure Python and the C++ implementation of Python, but not upb Python.

Removing setup.py and setup.cfg support from GitHub

In the 26.x release, setup.py and setup.cfg will no longer be present in the python/ directory of the GitHub repository or GitHub release tarballs. This means it will no longer be possible to build a Python package directly from the GitHub repo or release tarball.

The Python source packages published on PyPI will continue to have a setup.py in the top-level directory. This is the supported and recommended way of building Python binary packages, for users who do not want to use the binary packages that we distribute on PyPI.

For more information, see #15671.

Timestamps are checked for validity

In v26, the system will check if Timestamp values are valid. Seconds must be in the range [-62135596800, 253402300799] and nanos must be in range [0, 999999999]. Values outside those ranges will raise an exception.

Remove deprecated syntax accessor

We plan to remove the deprecated syntax accessor, FileDescriptor.syntax, in v26. We plan to add FileDescriptor.edition in its place.

UnknownFields support removal

In v25 message.UnknownFields() was deprecated in pure Python and C++ extensions. We plan to remove it v26. Use the new UnknownFieldSet(message) support in unknown_fields.py as a replacement.

More details about all of these changes will be available in the corresponding release notes.

Ruby Breaking Changes

  • Fix RepeatedField#each_index to have the correct semantics. (#11767)
  • Remove Ruby DSL and associated compatibility code, which will complete the migration announced in April.
  • Message#to_h fixes:
    • Remove unset oneof fields. (#6167)
    • Remove unset sub-message fields
  • Use message’s pool for encode_json/decode_json.
  • Remove the deprecated syntax accessor, FileDescriptor.syntax and add semantic checks in its place:
    • FieldDescriptor.has_presence to test if a field has presence.
    • FieldDescriptor.is_packed to test if a repeated field is packed.
    • FieldDescriptor.requires_utf8_validation to test if a string field requires UTF-8 validation.
    • EnumDescriptor.is_closed to test if an enum is closed.

Freeze Is Now Recursive in Ruby

Starting in the 26.x line, when freeze is applied it will be applied recursively, affecting all sub-messages, maps, and repeated fields.

upb Breaking Changes

The following changes are planned for the 26.x line: