To create a new error in Go with a fixed text message, use errors.New from the standard library errors package—the same API people look up as golang new error, golang errors.new, errors.new golang, or go errors new. When the message should include formatted values, use fmt.Errorf; when you need one stable value to compare with errors.Is, declare a package-level sentinel such as var ErrFoo = errors.New("...") and return that variable. For returning and handling errors in callers, see returning errors in Go.
Tested with Go 1.24 on Linux.
Create a golang new error with errors.New
func New(text string) error returns an error whose Error() string is exactly text. It is the usual answer when someone searches golang error new or new error golang and wants a fixed message with no formatting.
package main
import (
"errors"
"fmt"
)
func main() {
err := errors.New("this is a new error")
if err != nil {
fmt.Println(err)
}
}You should see the message printed on one line (the same string you passed to errors.New).
Return a golang new error from your own function
Validate input and return nil when there is no failure:
package main
import (
"errors"
"fmt"
"strings"
)
func checkStartsWithS(str string) error {
if !strings.HasPrefix(str, "S") && !strings.HasPrefix(str, "s") {
return errors.New("invalid string: must start with S")
}
return nil
}
func main() {
for _, s := range []string{"Hello", "Sorry"} {
if err := checkStartsWithS(s); err != nil {
fmt.Println(err)
} else {
fmt.Println("valid string")
}
}
}invalid string: must start with S
valid stringEach call to errors.New is a different value
For debugging and tests it matters: two separate calls to errors.New with the same string still produce different values, so == is false unless both sides are the exact same variable.
package main
import (
"errors"
"fmt"
)
func main() {
a := errors.New("x")
b := errors.New("x")
fmt.Println(a == b)
}falseIf you need a single shared sentinel error, declare it once at package scope: var ErrInvalid = errors.New("invalid") and return that same variable.
fmt.Errorf for messages with context (and %w wrapping)
fmt.Errorf is how you golang create error messages that include numbers, names, or other values (another common phrasing is golang create new error with context). It still returns a value of type error.
package main
import "fmt"
func main() {
const name, id = "Daniel", 17
ids := map[int]string{1: "Anna", 2: "Bob", 5: "Harry", 7: "Chris", 8: "Cody", 18: "Ron"}
if _, ok := ids[id]; !ok {
err := fmt.Errorf("user %q (id %d) not found", name, id)
fmt.Println(err.Error())
}
}You should see user "Daniel" (id 17) not found.
When you wrap another error, use %w so errors.Is and errors.Unwrap work:
package main
import (
"errors"
"fmt"
)
var ErrNotFound = errors.New("not found")
func lookup(id int) error {
if id != 1 {
return fmt.Errorf("user %d: %w", id, ErrNotFound)
}
return nil
}
func main() {
err := lookup(2)
fmt.Println(errors.Is(err, ErrNotFound))
}trueCustom types and the built-in error interface
Go’s built-in error interface is only Error() string. Any named type with that method satisfies error; you do not redeclare the interface in your package (doing so shadows the name error and confuses readers).
A small custom type can carry extra data for logging or errors.As:
package main
import (
"errors"
"fmt"
)
type NegativeInputError struct {
Value int
}
func (e NegativeInputError) Error() string {
return fmt.Sprintf("negative input: %d", e.Value)
}
func sqrtNonNeg(x int) (float64, error) {
if x < 0 {
return 0, NegativeInputError{Value: x}
}
return float64(x), nil
}
func main() {
_, err := sqrtNonNeg(-3)
var neg NegativeInputError
if errors.As(err, &neg) {
fmt.Println("caught", neg.Value)
}
}For more background on interfaces in general, see interfaces in Go.
Summary
Creating errors in Go starts with errors.New for a plain fixed string, package-level var Err = errors.New(...) when you need a stable sentinel, and fmt.Errorf when the message should include formatted context or wrap another error with %w for errors.Is. Separate calls to errors.New with identical text are still different values for ==. Custom types with an Error method implement the same error interface when you need richer inspection with errors.As.

