For syntactically invalid strings that have an overflowing syntactically valid prefix, strconv.ParseUint opts to report ErrRange instead of ErrSyntax, in contrast to its doc comment:
The errors that ParseInt returns have concrete type *NumError and include err.Num = s. If s is empty or contains invalid digits, err.Err = ErrSyntax and the returned value is 0; if the value corresponding to s cannot be represented by a signed integer of the given size, err.Err = ErrRange and the returned value is the maximum magnitude integer of the appropriate bitSize and sign.
--https://pkg.go.dev/strconv@go1.26.1#ParseUint (accessed 2026-03-26), https://pkg.go.dev/strconv@go1.26.1#ParseInt (accessed 2026-03-26)
This behaviour has been exhibited for over seventeen years, and can still be observed in Go 1.26.1:
// Cf. https://jfrech.de/blog/300 (accessed 2026-04-06)
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
x, err := strconv.ParseUint(strings.Repeat("9", 20)+"nine", 10, 64)
fmt.Println(x)
fmt.Println(err)
}
// go version go1.26.1 linux/amd64
// Output:
// 18446744073709551615
// strconv.ParseUint: parsing "99999999999999999999nine": value out of range
I've written about this behaviour, a −40% performance gain in a micro-benchmark on one specific CPU and applicability of AVX2 intrinsics to parsing decimal integers on my blog: cf. https://jfrech.de/blog/300
For syntactically invalid strings that have an overflowing syntactically valid prefix, strconv.ParseUint opts to report ErrRange instead of ErrSyntax, in contrast to its doc comment:
This behaviour has been exhibited for over seventeen years, and can still be observed in Go 1.26.1:
I've written about this behaviour, a −40% performance gain in a micro-benchmark on one specific CPU and applicability of AVX2 intrinsics to parsing decimal integers on my blog: cf. https://jfrech.de/blog/300