Why Go Will NEVER Fix Error Handling
Based on The PrimeTime's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Go is pausing error-handling syntax work for the foreseeable future because none of the proposals reached broad consensus under its proposal process.
Briefing
Go’s long-running effort to reduce the boilerplate of error handling is effectively stalled: after multiple Go-team proposals and hundreds of community alternatives, the project is choosing to stop pursuing new error-handling syntax “for the foreseeable future.” The core issue is familiar to Go programmers—repeated patterns like `if err != nil { return ... }` can turn real work into a thin layer surrounded by error-checking noise, especially in code that makes many API calls.
The Go team’s history shows how hard this problem has been to solve without breaking Go’s design priorities. The first major attempt dates to 2018, when Russ Cox described a “check and handle” approach based on earlier draft work by Marcel von Leoen Lohisen Laisen. That design included a broad comparison of alternatives, but it was judged too complicated. In 2019, a simplified “try” proposal followed, turning “check” into a `try` built-in function and omitting “handle.” While the mechanism was tested with a rewriting tool and prototyped in the compiler, it changed control flow by returning from the enclosing function—sometimes from deeply nested expressions—making the behavior harder to see and harder to reason about.
A later round of proposals continued to iterate, including a more recent direction attributed to Jimmy FRA that revisits the original check-and-handle concept with modifications intended to address earlier shortcomings. Yet even these refinements failed to win broad support. The proposal process itself becomes a bottleneck: when general consensus can’t be found in tracker discussions, proposals get declined, and without consensus the decision path ultimately falls to Go architects. The result is that none of the major syntax proposals reached the level of agreement needed to move forward.
One of the most concrete alternatives discussed is the “question mark” operator, borrowed from Rust’s ergonomics. Informal studies where programmers were shown Go code using this operator found that most participants correctly inferred its meaning. Ian Lance Taylor also built a tool to convert ordinary Go code into the proposed syntax and prototyped it in the compiler. Still, the proposal attracted a flood of comments and preferences for minor tweaks, and broad support never materialized.
Beyond consensus, the Go team highlights practical costs. Language changes are expensive: they require updating code, documentation, and tooling, and the Go team is small with many competing priorities. There are also arguments for leaving things alone—Go already has a workable error-handling model, and Go’s culture favors avoiding multiple ways to do the same thing. Even so, the team acknowledges the user pain: error handling remains a top complaint in developer surveys, and the lack of syntax support is most noticeable for programmers coming from languages with built-in error propagation.
In the end, the decision is pragmatic rather than optimistic. The team will stop pursuing syntax changes for error handling and close proposals focused primarily on error-handling syntax. The hope is that future work—possibly around improving how errors are constructed and augmented, or around better tooling and visibility—will clarify whether the real bottleneck is syntactic verbosity or the broader challenge of making errors useful and readable.
Cornell Notes
Go’s attempt to add new syntax to reduce error-handling boilerplate has stalled. After multiple proposals—including 2018 “check and handle,” a 2019 “try” built-in approach, and later ideas like a Rust-style question mark operator—none attracted the consensus needed to proceed under Go’s proposal process. The team cites both technical concerns (control-flow visibility, complexity) and social/process realities (hundreds of comments, lack of overwhelming agreement). The practical takeaway is a pause: for the foreseeable future, Go will stop pursuing error-handling syntax changes, even though error verbosity remains a top user complaint.
Why did the 2019 “try” proposal fail despite testing and compiler prototyping?
What made the “question mark” operator proposal attractive, and why didn’t it win?
How does Go’s proposal process influence whether error-handling syntax can land?
What costs does the Go team point to when deciding whether to change the language?
What tension does the team highlight between “Go already works” and the desire to reduce boilerplate?
Review Questions
- Which specific control-flow behavior of the 2019 `try` approach made it harder to review and reason about?
- What evidence supported the “question mark” operator’s usability, and what blocked it from becoming standard?
- Why does the Go team treat language changes as costly even when syntax ideas seem straightforward?
Key Points
- 1
Go is pausing error-handling syntax work for the foreseeable future because none of the proposals reached broad consensus under its proposal process.
- 2
The 2018 “check and handle” design was rejected as too complicated, even though it included extensive analysis and alternatives.
- 3
The 2019 “try” proposal was rejected largely because it could return from the enclosing function from deeply nested expressions, obscuring control flow.
- 4
A Rust-inspired “question mark” operator showed promising comprehension in informal studies and was prototyped, but it still failed to gain overwhelming support amid many tweak requests.
- 5
Go’s small team and the ecosystem-wide cost of language changes (code, docs, tools) make syntax changes hard to justify without strong agreement.
- 6
The team distinguishes between syntactic verbosity and the broader challenge of making errors useful, suggesting future work may focus more on error construction and tooling than syntax alone.