cockroachdb/errors: Go errors that survive the network
Go error library with error portability over the network
At a glance
- What is it?
- cockroachdb/errors is a drop-in replacement for github.com/pkg/errors and Go's standard errors package that adds protobuf encoding, PII-free reportable strings and cross-network errors.Is(). It suits distributed systems that ship mixed-version binaries; it is overkill for a single-process CLI.
- Who is it for?
- Adopt cockroachdb/errors if errors cross a process or version boundary in your system and you need errors.Is() to keep working after a protobuf round trip, or if you want PII-free reportable strings before shipping to Sentry. Do not adopt it for a single-binary CLI where standard errors and fmt.Errorf with %w already cover every case, because the gogo/protobuf and grpc dependencies in go.mod are not free.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem: error identity dies at the process boundary
Go's errors.Is() compares an error against a sentinel by walking the Unwrap chain. That works inside one process. The moment an error is serialized to a wire format and reconstructed on the other side, the chain is gone: what arrives is a fresh value, and errors.Is() returns false even though the original error was, semantically, the same one. In a distributed system with mixed-version binaries this gets worse, because the receiving side may not even have the code that produced the error.
The README frames the project as a drop-in replacement for github.com/pkg/errors and the standard errors package, and the feature table lists what it adds on top: transparent protobuf encode/decode with forward compatibility, errors.Is() that recognizes errors across the network, and comprehensive support for PII-free reportable strings. Forward compatibility, as the README defines it, means the library can recognize and handle error types it does not know about, for example when a newer package version sends a new error object to an older system. That is the whole point: not prettier stack traces, but error identity that survives a round trip.
How encoding works, and why gogo/protobuf is in go.mod
The mechanism is a pair of functions, errors.EncodeError() and errors.DecodeError(), backed by the errorspb package in the repository root. Wrapped errors are flattened into a protobuf message that carries the chain, then rebuilt on the other side. The README's feature table calls this transparent protobuf encode/decode, and the repository layout confirms it: errorspb/ holds the generated types, and the top level carries Makefile.update-protos, so the .proto files are regenerated rather than hand-written.
That choice has consequences. The go.mod requires github.com/gogo/protobuf v1.3.2 with the comment that it is gogoproto 1.2-compatible, for CRDB, plus gogo/status and gogo/googleapis. gogo/protobuf is a fork of the older Google protobuf API, not google.golang.org/protobuf, which is also present at v1.36.10. So a service that has already moved to the modern protobuf runtime ends up carrying both. For CockroachDB, whose wire format is built on that fork, this is the only workable option. For everyone else it is a real dependency cost, and it is the first thing to weigh before adopting.
Installing it and making an error survive a round trip
The module path is github.com/cockroachdb/errors. Add it with go get, then import it under the conventional alias. Because the API mirrors the standard library, the import line is the only change for code that already uses errors.New, errors.Wrap, errors.Is and errors.As.
go get github.com/cockroachdb/errorsThe README's How to use section gives the construction and wrapping rules: construct with errors.New() or the other leaf constructors, wrap with errors.Wrap() or another wrapper, and test identity with errors.Is() as usual. The one claim worth checking against your own types is that errors.Is() works even if the error has traversed the network. The README documents the encode and decode entry points as errors.EncodeError() and errors.DecodeError(); the call signatures and context arguments are not shown in the README, so read the package documentation on pkg.go.dev before wiring them in.
On the receiving side, an errors.Is() check against a sentinel both processes know should hold. If you are replacing os.IsPermission, os.IsTimeout, os.IsExist or os.IsNotExist, the README directs you to the oserror sub-package instead, because those standard functions cannot see through wrapping layers.
PII-free details and the Sentry path
The library ships a redaction story, not just an encoding story. safedetails/ and the errors.SafeFormatError()/SafeFormatter API let an error carry a reportable string that is safe to send to a third party, while the full detail stays local. The report/ package provides the opt-in Sentry.io integration, and go.mod pins github.com/getsentry/sentry-go v0.46.0. The README describes the reporting mechanism as automatically formatting error details and stripping them of PII.
This is the part most teams will actually feel. An error message that embeds a user ID, an email or a row value is a data-protection problem the moment it lands in an external error tracker, and retrofitting redaction onto free-form fmt.Errorf strings is unpleasant. Having a SafeFormatter interface from the start is a better shape. The trade-off is that it only helps if the code that constructs errors uses it; the library cannot redact a string that was already interpolated into an ordinary error.
Where it is the wrong tool
The dependency weight is the first limitation. A program that only needs wrapped errors and errors.Is() inside one process gets everything it needs from Go 1.13's standard errors package, and fmt.Errorf with %w costs nothing. Pulling in gogo/protobuf, gogo/status, gogo/googleapis, grpc and sentry-go to get stack traces and sentinels is a poor trade for a CLI or a small service.
The second is that the network portability only covers errors that travel as encoded values. If your service boundary is JSON, gRPC status details you have not wired up, or an HTTP body you formatted yourself, EncodeError and DecodeError never run and the guarantees do not apply. The README documents the encoding path and the grpc/ and extgrpc/ packages, but it does not document rollback or a downgrade path for an error payload a peer cannot parse; that behaviour has to be established from the code and your own tests. The repository layout is also wide, with roughly twenty top-level API files (assert_api.go, barriers_api.go, domains_api.go, errutil_api.go and so on), which is a lot of surface for a library whose core promise is one round trip.
How it compares to pkg/errors and errgroup-style handling
The clearest alternative is github.com/pkg/errors, which the README explicitly names as the package this one replaces. pkg/errors gives you Wrap, WithStack and Cause, and it is small. It has no wire format at all: an error wrapped with pkg/errors cannot be reconstructed on another host with its identity intact, and it predates errors.Is and errors.As, so it does not interoperate with the standard library's matching functions. Migrating from it to cockroachdb/errors is mostly an import swap, which is why the drop-in claim holds.
The other common pattern is to stop passing errors and pass a status code plus a message string across the boundary, reconstructing a fresh error on the far side. That is what gRPC's status model encourages, and it is genuinely simpler. The difference is that you lose the cause chain: the receiving service can branch on a code, but it cannot ask errors.Is(err, ErrRetryable) about a wrapped inner error, and it cannot recover the structured detail. cockroachdb/errors keeps the chain in the payload, which is more machinery and more bytes for a capability that plain status codes do not offer.
Maintenance, licence and upgrade cost
The last push to master was on 2026-09-26, and the most recent release is v1.14.0 from 2026-06-18, preceded by v1.13.0 in April 2026 and v1.12.0 in May 2025. The repository is not archived. The gap between v1.12.0 and v1.13.0 is roughly a year, so releases arrive when the parent project needs them rather than on a schedule.
The module requires go 1.25.0, which sets a floor on the toolchain for anyone importing it. The Apache-2.0 licence is permissive and imposes no copyleft obligation on your own code, but the dependency tree is the part to review: gogo/protobuf, gogo/status and google.golang.org/grpc all come along, and their licences and update cadence become yours to track. Upgrading the library can move those pins, so treat a version bump as a dependency review rather than a one-line change. None of this is legal advice; read the licence texts and your own policy.
Editorial conclusion
Adopt cockroachdb/errors if errors cross a process or version boundary in your system and you need errors.Is() to keep working after a protobuf round trip, or if you want PII-free reportable strings before shipping to Sentry. Do not adopt it for a single-binary CLI where standard errors and fmt.Errorf with %w already cover every case, because the gogo/protobuf and grpc dependencies in go.mod are not free. Before committing, verify that EncodeError/DecodeError round-trips your own custom error types, and check how the library behaves when a newer peer sends an error type your binary does not know.
Frequently asked questions
Is cockroachdb/errors a drop-in replacement for github.com/pkg/errors?
The README states that the library aims to be used as a drop-in replacement for github.com/pkg/errors and Go's standard errors package. It provides errors.Cause() and errors.Unwrap() for compatibility with other error packages, alongside UnwrapOnce() and UnwrapAll().
How does errors.Is() work across the network in cockroachdb/errors?
Errors are encoded with errors.EncodeError() and rebuilt with errors.DecodeError() using the protobuf types in the errorspb package, so the cause chain travels with the payload. The README lists errors.Is() recognizing errors across the network as a feature unique to this library.
What does forward compatibility mean for cockroachdb/errors?
The README defines it as the ability to recognize and handle network communication of error types the library does not know about, for example when a newer version of a package sends a new error object to a system running an older version.
Does cockroachdb/errors send error details to Sentry?
The README describes an opt-in Sentry.io reporting mechanism that automatically formats error details and strips them of PII, backed by the report/ package and github.com/getsentry/sentry-go in go.mod. It is opt-in, not enabled by default.
Which Go version does cockroachdb/errors require?
The go.mod file declares go 1.25.0, so that is the minimum toolchain the module expects. Importing it also brings in gogo/protobuf, gogo/status, google.golang.org/grpc and sentry-go as direct requirements.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cockroachdb-errors)