errors.As searches an error chain for an error of a requested type and assigns the matching value to a variable. Use it when handling depends on details carried by a concrete error—such as a database error code—rather than merely whether a sentinel error occurred. This lets an adapter inspect an infrastructure-specific failure, then return a stable application-level error instead of exposing driver details. section 10.2.4 section 10.6
Pass a pointer to the variable that will receive the match. The requested type must implement error. When an error type implements Error with a pointer receiver, its pointer form implements error, so extraction needs a pointer to that pointer: declare var serr *sqlite.Error, then call errors.As(err, &serr). Declaring serr as sqlite.Error instead fails because that value type does not implement error. section 10.2.4
Translate a SQLite duplicate-key failure
Keep driver inspection in a small helper. It extracts *sqlite.Error from err, checks its code, and reports whether the failure is a primary-key violation: var serr *sqlite.Error if errors.As(err, &serr) { return serr.Code() == 1555 } return false Shorten can then translate that condition to a wrapped link.ErrConflict. Callers receive a meaningful conflict result and can retry with another key, while other failures become an application internal error. section 10.2.4
Listing 10.8 Detecting constraint errors (link/sqlite/sqlite.go)
package sqlite
import (
// _ "modernc.org/sqlite" #1
. . .
"errors"
"modernc.org/sqlite" #2
)
. . .
func isPrimaryKeyViolation(err error) bool {
var serr *sqlite.Error #3
if errors.As(err, &serr) { #4
return serr.Code() == 1555 #5
// See: sqlite.org/rescode.html#constraint_primarykey
}
return false
}
Inspect the complete helper that extracts the SQLite driver error before checking its primary-key constraint code. section 10.2.4
This pattern keeps concrete dependencies at the boundary that owns them. A storage implementation may recognize its driver’s error type, but its clients can depend on domain errors such as ErrConflict. Integration tests can assert the public result with errors.Is, verifying that duplicate keys do not leak SQLite’s raw constraint message. section 10.2.3 section 10.2.4
errors.As also supports custom error types that carry context. For example, a *NotFoundError with an ID can be extracted and read after a successful match. Take care not to return a nil pointer of a custom error type as success: an error interface containing that typed nil is not nil, and later use can panic. section 8.2.1
Use errors.As when these conditions hold:
- A wrapped error chain may contain a concrete error whose fields or methods determine handling. section 10.2.4
- The receiving variable has the matching error type, with pointer indirection matching how that type implements error. section 10.2.4
- The concrete error is translated or interpreted at an implementation boundary, leaving callers with meaningful application-level errors. section 10.2.4 section 10.6



