valyala/fasthttp · error

empty hex number

Error message

empty hex number

What it means

errEmptyHexNum is returned by readHexInt when the chunked transfer-encoding size line contains no hexadecimal digits. readHexInt parses chunk sizes while reading chunked request/response bodies, so this error indicates a malformed chunked stream rather than bad user code. It is a declared sentinel, comparable with errors.Is.

Source

Thrown at bytesconv.go:368

}

// ParseUfloat parses unsigned float from buf.
func ParseUfloat(buf []byte) (float64, error) {
	// The implementation of parsing a float string is not easy.
	// We believe that the conservative approach is to call strconv.ParseFloat.
	// https://github.com/valyala/fasthttp/pull/1865
	res, err := strconv.ParseFloat(b2s(buf), 64)
	if res < 0 {
		return -1, errors.New("negative input is invalid")
	}
	if err != nil {
		return -1, err
	}
	return res, err
}

var (
	errEmptyHexNum    = errors.New("empty hex number")
	errTooLargeHexNum = errors.New("too large hex number")
)

func readHexInt(r *bufio.Reader) (int, error) {
	var k, i, n int
	for {
		c, err := r.ReadByte()
		if err != nil {
			if err == io.EOF && i > 0 {
				return n, nil
			}
			return -1, err
		}
		k = int(hex2intTable[c])
		if k == 16 {
			if i == 0 {
				return -1, errEmptyHexNum
			}

View on GitHub (pinned to c96f600972)

Solutions

  1. Verify the sending client/proxy implements chunked transfer encoding correctly; test with curl or a reference client.
  2. Handle the error where you read the body and return 400 Bad Request, since the request framing is corrupt.
  3. If streams come from an untrusted network, cap read sizes/timeouts (fasthttp ReadTimeout, max body size) so malformed streams fail fast.
  4. Ensure intermediaries are not mangling the body (some proxies re-chunk or strip chunk extensions incorrectly).
Defensive patterns

Strategy: try-catch

Validate before calling

// Cannot pre-validate chunk framing; instead bound the read:
server := &fasthttp.Server{
    ReadTimeout: 10 * time.Second,
    MaxRequestBodySize: 8 << 20,
}

Try / catch

if err := bodyHandler(ctx); err != nil {
    if err.Error() == "empty hex number" {
        ctx.Error("malformed chunked encoding", fasthttp.StatusBadRequest)
        return
    }
    return err
}

Prevention

When it happens

Trigger: Reading a chunked body where a chunk-size line is empty or starts with a non-hex character, e.g. a client sending '\r\n' where a hex length was expected, or a truncated chunked stream.

Common situations: Misbehaving HTTP clients or proxies emitting invalid chunked encoding; connections cut mid-stream so the size line never arrives; custom/proxied payloads with framing mistakes.

Related errors


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/fdb1ab11da390b8f. Report an issue: GitHub.