Skip to content

proposal: explicitly exclude error messages from the Go 1 compatibility promise #78991

@jub0bs

Description

@jub0bs

The document that specifies the Go 1 compatibility promise ("go1compat" for short) lists a number of exclusions:

  • Security. A security issue in the specification or implementation may come to light whose resolution requires breaking compatibility. We reserve the right to address such security issues.
  • Unspecified behavior. The Go specification tries to be explicit about most properties of the language, but there are some aspects that are undefined. Programs that depend on such unspecified behavior may break in future releases.
  • [...]

However, there's no explicit exclusion for error messages. You perhaps don't perceive such omission as problematic. In his GopherCon 2020 talk, @jba stated

[...] we all understand that the text of error messages is for people and for people only. It is emphatically not part of the API like values and types are.

Arguably, most seasoned Gophers implicitly understand this: the wording of error messages falls outside the go1compat, it may change from one release to the next, and programs should not depend on the result of an error's Error method (e.g. via string matching).

However, this exclusion may not be obvious to all Gophers, esp. newcomers to the language; and some Gophers may be aware of it but fail to anticipate how disregarding it makes their programs brittle. A casual search on GitHub indeed reveals that distressingly many Go programs do rely on string matching to extract data from error messages or distinguish one failure condition from another. Not only does this lack of clarity about error messages fail to discourage bad practices, it somewhat hinders the evolution of code covered by the go1compat. A recent enough example comes to mind:

// MaxBytesError is returned by [MaxBytesReader] when its read limit is exceeded.
type MaxBytesError struct {
	Limit int64
}

func (e *MaxBytesError) Error() string {
	// Due to Hyrum's law, this text cannot be changed.
	return "http: request body too large"
}

Because, prior to http.MaxBytesError's addition in Go 1.19, many importers of the net/http package would string-match the message of the hitherto non-exported error, @earthboundkid did not feel free to alter the error message for fear of breaking such programs, even though she might have wanted to (perhaps to include the value of the Limit field).

Therefore, I believe that the go1compat should be updated to explicitly state that it excludes error messages. Doing so would clarify expectations and instil better error-checking and error-reporting practices in the community. Instead of string-matching error messages, dependents who need to programmatically inspect an error would understand that they should nudge the maintainers of the package to export, in a subsequent release, an error variable or a concrete error type.

(You might argue that the go1compat is set in stone, that it can no longer be updated, but there is precedent for amending it; see, in particular, CL 162060043 and CL 12460.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationIssues describing a change to documentation.Proposal

    Type

    No type

    Projects

    Status

    No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions