{"record":{"id":"0fa8ff7555e3d391","repo":"valyala/fasthttp","slug":"unexpected-first-char-found-expecting-0-9","errorCode":null,"errorMessage":"unexpected first char found: expecting 0-9","messagePattern":"unexpected first char found: expecting 0-9","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"bytesconv.go","lineNumber":277,"sourceCode":"}\n\n// ParseUint parses uint from buf.\n//\n// A value too large for an int is an error rather than a wrapped result, so\n// ParseUint accepts exactly the unsigned decimal strings whose value fits in an\n// int on the current platform.\nfunc ParseUint(buf []byte) (int, error) {\n\tv, n, err := parseUintBuf(buf)\n\tif n != len(buf) {\n\t\treturn -1, errUnexpectedTrailingChar\n\t}\n\treturn v, err\n}\n\nvar (\n\terrEmptyInt               = errors.New(\"empty integer\")\n\terrIPv4PartTooLarge       = errors.New(\"ip part cannot exceed 255\")\n\terrUnexpectedFirstChar    = errors.New(\"unexpected first char found: expecting 0-9\")\n\terrUnexpectedTrailingChar = errors.New(\"unexpected trailing char found: expecting 0-9\")\n\terrTooLongInt             = errors.New(\"too long int\")\n)\n\nconst (\n\t// maxIntDiv10 is the largest accumulator that can still take another digit.\n\t// Anything above it overflows an int when multiplied by 10.\n\tmaxIntDiv10 = math.MaxInt / 10\n\n\t// maxSafeIntDigits is how many leading decimal digits can never overflow an\n\t// int, whatever the word size: 10**18-1 fits a 64-bit int and 10**9-1 fits a\n\t// 32-bit one. Go defines strconv.IntSize as 32 or 64 and nothing else.\n\t// TestMaxSafeIntDigits checks both halves of that claim on the build's own\n\t// int size.\n\tmaxSafeIntDigits = 9 * (strconv.IntSize / 32)\n)\n\nfunc parseUintBuf(b []byte) (int, int, error) {","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/bytesconv.go#L259-L295","documentation":"errUnexpectedFirstChar is returned by parseUintBuf and parseIPv4Octet when the input does not begin with a digit 0-9. Numeric parsing requires the first byte to be a digit, so leading signs, spaces, letters, or punctuation trigger this sentinel error. It surfaces through ParseUint and ParseIPv4.","triggerScenarios":"ParseUint([]byte(\" 42\")) (leading space), ParseUint([]byte(\"-1\")) (minus sign), ParseIPv4 on values like \"abc.1.2.3\" or \".1.2.3\".","commonSituations":"Whitespace-padded header values (Content-Length: ' 123'); signed numbers passed where unsigned parsing is expected; hostnames or enum strings accidentally fed to numeric parsing.","solutions":["Trim leading whitespace with bytes.TrimSpace before parsing.","Reject or separately handle negative numbers — ParseUint is unsigned, so use strconv.Atoi if signs are legitimate.","Pre-validate the first byte: if buf[0] < '0' || buf[0] > '9', handle the input before calling ParseUint.","Check the call site: a non-numeric string reaching a numeric parser usually means the wrong field was passed."],"exampleFix":"// before\nn, err := fasthttp.ParseUint(rawHeader)\n// after\nrawHeader = bytes.TrimSpace(rawHeader)\nif len(rawHeader) == 0 || rawHeader[0] < '0' || rawHeader[0] > '9' {\n    return 0, fmt.Errorf(\"not an unsigned number: %q\", rawHeader)\n}\nn, err := fasthttp.ParseUint(rawHeader)","handlingStrategy":"validation","validationCode":"func parseUintClean(b []byte) (int, error) {\n    b = bytes.TrimSpace(b)\n    if len(b) == 0 || b[0] < '0' || b[0] > '9' {\n        return 0, fmt.Errorf(\"expected unsigned int, got %q\", b)\n    }\n    return fasthttp.ParseUint(b)\n}","typeGuard":"func startsWithDigit(b []byte) bool {\n    return len(b) > 0 && b[0] >= '0' && b[0] <= '9'\n}","tryCatchPattern":"n, err := fasthttp.ParseUint(b)\nif err != nil && err.Error() == \"unexpected first char found: expecting 0-9\" {\n    return 0, fmt.Errorf(\"%q is not a number\", b)\n}","preventionTips":["TrimSpace all header values before numeric parsing","Use signed parsers (strconv.Atoi) when '-' is legitimate","Confirm the field being parsed is actually numeric","Reject non-digit input early with a clear message"],"tags":["integer-parsing","input-validation","whitespace"],"backgroundTag":"non-numeric-input","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}