Skip to content

dependencies: migrate from gogo/protobuf to google.golang.org/protobuf#165

Open
liran-funaro wants to merge 1 commit into
cockroachdb:masterfrom
liran-funaro:remove-gogo
Open

dependencies: migrate from gogo/protobuf to google.golang.org/protobuf#165
liran-funaro wants to merge 1 commit into
cockroachdb:masterfrom
liran-funaro:remove-gogo

Conversation

@liran-funaro

@liran-funaro liran-funaro commented Jul 12, 2026

Copy link
Copy Markdown

github.com/gogo/protobuf, along with the related github.com/gogo/status and github.com/gogo/googleapis, is deprecated and unmaintained. This migrates the whole module to the standard, maintained protobuf stack it already depended on: google.golang.org/protobuf (+ anypb), google.golang.org/grpc/status, and
google.golang.org/genproto/googleapis/rpc/status.

The .proto files are regenerated with the standard protoc-gen-go and protoc-gen-go-grpc, dropping the custom protoc-gen-gogoroach plugin and all gogoproto options, and the hand-written code is adapted to the v2 runtime:

  • errbase packs and unpacks error detail payloads with anypb.New and (*anypb.Any).UnmarshalNew, resolving types through the standard protoregistry instead of gogo's registry.
  • The previously non-nullable embedded fields (Details, Cause, ErrorTypeMark) are now pointers, read through the generated nil-safe getters. DecodeError takes *EncodedError and GetTypeMark returns *errorspb.ErrorTypeMark accordingly.
  • extgrpc and grpc/middleware use google.golang.org/grpc/status. Because the standard Any can hold standard protobufs directly, the former gogo/standard status split collapses into a single path, and google.rpc.Status now comes from genproto with the same type URL.
  • go.mod drops all three gogo modules.

Wire compatibility is preserved: no proto package/message name or field number changes, and google.protobuf.Any type URLs are unchanged, so errors serialized by the previous gogo-based version still decode here and vice versa.

This is a breaking API change (major version): the encoder/decoder registration interfaces now reference the v2 proto.Message, so consumers that register custom error types must supply standard-protobuf payloads. Errors originally produced as github.com/gogo/status types decode to an opaque error (message and safe details preserved) rather than being reconstructed as a gRPC status.

@cockroachlabs-cla-agent

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

github.com/gogo/protobuf, along with the related github.com/gogo/status
and github.com/gogo/googleapis, is deprecated and unmaintained. This
migrates the whole module to the standard, maintained protobuf stack it
already depended on: google.golang.org/protobuf (+ anypb),
google.golang.org/grpc/status, and
google.golang.org/genproto/googleapis/rpc/status.

The .proto files are regenerated with the standard protoc-gen-go and
protoc-gen-go-grpc, dropping the custom protoc-gen-gogoroach plugin and
all gogoproto options, and the hand-written code is adapted to the v2
runtime:

- errbase packs and unpacks error detail payloads with anypb.New and
  (*anypb.Any).UnmarshalNew, resolving types through the standard
  protoregistry instead of gogo's registry.
- The previously non-nullable embedded fields (Details, Cause,
  ErrorTypeMark) are now pointers, read through the generated nil-safe
  getters. DecodeError takes *EncodedError and GetTypeMark returns
  *errorspb.ErrorTypeMark accordingly.
- extgrpc and grpc/middleware use google.golang.org/grpc/status. Because
  the standard Any can hold standard protobufs directly, the former
  gogo/standard status split collapses into a single path, and
  google.rpc.Status now comes from genproto with the same type URL.
- go.mod drops all three gogo modules.

Wire compatibility is preserved: no proto package/message name or field
number changes, and google.protobuf.Any type URLs are unchanged, so
errors serialized by the previous gogo-based version still decode here
and vice versa.

This is a breaking API change (major version): the encoder/decoder
registration interfaces now reference the v2 proto.Message, so consumers
that register custom error types must supply standard-protobuf payloads.
Errors originally produced as github.com/gogo/status types decode to an
opaque error (message and safe details preserved) rather than being
reconstructed as a gRPC status.

Signed-off-by: Liran Funaro <liran.funaro@gmail.com>
@liran-funaro liran-funaro changed the title errors: migrate from gogo/protobuf to google.golang.org/protobuf dependencies: migrate from gogo/protobuf to google.golang.org/protobuf Jul 14, 2026
@liran-funaro

Copy link
Copy Markdown
Author

Migrating off gogo protobuf (cockroachdb/errors)

This release replaces the deprecated gogo protobuf stack
(github.com/gogo/protobuf, github.com/gogo/status,
github.com/gogo/googleapis) with the standard
google.golang.org/protobuf stack. It is a breaking, major-version change.

Are you affected?

Not affected (most users): code that only uses errors.New, Wrap,
Errorf, %+v/%v, errors.Is/As/Unwrap, hints, safe details,
telemetry keys, stack traces, join, barriers, domains. Bump the
dependency and rebuild — no code changes.

Affected: code that does any of:

  • registers a custom error type with a proto payload
    (RegisterLeafEncoder / RegisterWrapperEncoder / RegisterLeafDecoder /
    RegisterWrapperDecoder / RegisterMultiCause{Encoder,Decoder} /
    RegisterWrapperEncoderWithMessageType);
  • calls errors.EncodeError / errors.DecodeError directly;
  • touches errorspb.* types directly;
  • sends errors over gRPC via extgrpc and/or github.com/gogo/status.

What changed (API points)

  1. The encoder/decoder function types (LeafEncoder, LeafDecoder,
    WrapperEncoder, WrapperDecoder, MultiCauseEncoder,
    MultiCauseDecoder, WrapperEncoderWithMessageType) reference
    proto.Message, which is now google.golang.org/protobuf/proto.Message
    instead of the gogo one. A gogo-generated payload lacks ProtoReflect(),
    so it no longer satisfies the interface (compile error), and gogo types
    are not in the standard registry, so decode falls back to opaque.
  2. DecodeError now takes a pointer: DecodeError(ctx, enc *EncodedError).
    (EncodeError still returns EncodedError by value.)
  3. GetTypeMark now returns *errorspb.ErrorTypeMark.
  4. errorspb.* messages are now v2 messages: previously-embedded value
    fields are pointers (EncodedErrorLeaf.Details, EncodedWrapper.Cause,
    EncodedErrorDetails.ErrorTypeMark, EncodedErrorDetails.FullDetails),
    and they must not be copied by value (go vet copylocks).
  5. gRPC glue uses google.golang.org/grpc/status; the dedicated decoder for
    github.com/gogo/status-typed errors is removed.

Behavioral change

An error originally produced as a github.com/gogo/status error now decodes
to an opaque error (message and safe details preserved) instead of being
reconstructed as a gRPC status. Standard google.golang.org/grpc/status
errors are fully handled. Fix: use standard status.

Migration steps

  1. Triage. Search your repo:
    grep -rE 'errors.(Encode|Decode)Error|Register(Leaf|Wrapper|MultiCause)|errorspb.|/extgrpc|gogo/status'
    No hits -> just bump the dependency and rebuild. (If published as a Go
    major version, the import path becomes github.com/cockroachdb/errors/v2.)
  2. Regenerate your error-payload .proto files with the standard toolchain:
    replace protoc-gen-gogo / gogoroach with protoc-gen-go, delete the
    gogoproto import + options, and set a full go_package. This makes your
    payload types implement v2 proto.Message and register in the standard
    global registry (required for both compilation and decode).
  3. Swap proto imports in your encoder/decoder code:
    github.com/gogo/protobuf/proto -> google.golang.org/protobuf/proto
    github.com/gogo/protobuf/types (Any) -> google.golang.org/protobuf/types/known/anypb
  4. Add & to DecodeError calls: errors.DecodeError(ctx, &enc)
    (or pass the *EncodedError you already hold).
  5. GetTypeMark now returns *errorspb.ErrorTypeMark — adjust
    assignments/comparisons.
  6. If you read/build errorspb types directly, use the generated getters
    (GetDetails(), GetErrorTypeMark(), ...) and stop copying messages by value.
  7. gRPC: switch github.com/gogo/status -> google.golang.org/grpc/status.
    If you relied on gogo-status errors round-tripping, move to standard status.
  8. Verify: go build ./... then go vet ./... (copylocks surfaces any
    remaining by-value message copies).

For a typical single custom error type this is usually: regenerate one
.proto, change one import line, and add one & — plus the gRPC swap if
applicable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gogoprotobuf replacement

1 participant