AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Go error syntax closed; failure policy remains your team's job

Go's error-syntax decision leaves teams with practical choices about wrapping, reporting and recovery. Review failure paths before debating shorter code.

Citiți articolul în română

A Go service needs a clear answer to what happens after an operation fails. Shorter error checks could make that answer easier to scan, but they cannot choose it. The useful response to the language team's June 2025 decision is to agree how errors acquire context, where they are reported and who decides whether work can continue.

Looking back from November 2026, that is a more productive team discussion than treating the absence of new syntax as permission to leave failure behavior inconsistent. Error handling affects customer messages, repeated operations and the evidence available when someone investigates a failed job. Those decisions survive any spelling of an early return.

On 3 June 2025, Robert Griesemer explained the Go team's position: proposals had not achieved consensus, and further attempts to solve the syntax problem should stop for the foreseeable future. This was a governance decision under disagreement. It did not establish that repeated error checks impose no reading cost or that the language could never change.

Read a failure path from the customer's end

Start with an operation whose failure matters to the business. Identify what the caller knows when it fails, whether any change has already happened and whether repeating it could produce another change. A storage timeout and a rejected request may produce similar looking branches while requiring different responses.

A team should distinguish failure categories that change the next action. Invalid input may need a correction from the user. Temporary unavailability may permit another attempt. An uncertain result after submitting an external action may require reconciliation first. These are design choices to confirm against the actual service, rather than universal instructions to retry every network error.

That distinction also helps review the happy path. If creating an order succeeds but sending its confirmation fails, the application needs an explicit outcome. Reporting that the entire order failed could encourage a duplicate order. Silently discarding the communication error could leave the customer uninformed. A shorter return statement would leave that ambiguity intact.

This is an illustrative decision, not a report of a customer incident. Its value is that the team can describe an observable result: what the customer sees, what has been recorded and what an operator can safely do next. Reviewers can then assess the implementation against that result.

Add context where it becomes meaningful

Wrapping an error is useful when a layer knows something the underlying operation does not. The caller may need to know which business operation failed, while the underlying error remains available for programmatic inspection. Context should explain the task without exposing secrets or copying an entire customer record into diagnostic text.

A wrapping rule should also say what remains stable for callers. If a caller relies on a failure category, converting it into an arbitrary sentence can break that relationship. Conversely, exposing every low-level implementation detail may tie an interface to a dependency that the team later needs to replace. Decide deliberately which information crosses the interface.

Avoid making every function add its own near-identical prefix. A long chain of repeated labels can hide the useful detail. Review the final message seen by the person who will act on it. The objective is enough context to locate the failed operation and enough retained meaning to choose a response.

The related February proposal for question-mark forms records an attempted language design, rather than shipped syntax. Its existence demonstrates that people were trying to reduce repetition. It supplies no evidence that an application adopting a compact form would automatically produce better diagnostic context.

Decide where reporting happens

Returning an error and reporting it have separate purposes. A lower layer can return information that its caller can still handle. A boundary with responsibility for the operation can decide whether to emit a diagnostic event, show a message or schedule further work. Logging at every layer can make one failure look like several independent incidents.

There are exceptions. Different boundaries may need different records, particularly when distinct systems own different consequences. The useful rule is to define the purpose of each record and connect related records, rather than prohibit all repeated reporting. An audit record of an attempted business action and an operational alert are not interchangeable.

Recovery needs the same ownership. A library should not assume that its caller wants a customer-visible operation repeated. A request handler should not assume that returning an error undoes an action already accepted elsewhere. Put the retry or reconciliation decision where the relevant business information exists.

The strongest case for shorter syntax still matters

Repetition can obscure the main computation. In a sequence of calls with simple failure propagation, a compact construct could reduce visual noise. That is a credible readability argument. A team need not deny it to accept the maintainers' decision under the proposal process.

The limitation is that scanning cost and failure policy require different evidence. Review a representative function for readability; review its consequential failure paths for correctness. Counting fewer lines proves neither better recovery nor better user communication. A small utility with no external side effects may need far less policy than a service coordinating several systems.

For custom software development, ask for a bounded failure-path review attached to work already planned. It should identify the returned meaning, reporting owner and recovery decision for a consequential operation. That produces an agreement the team can maintain in ordinary Go today, while leaving future syntax debates to the language process.