valyala/fasthttp · error · ErrBrokenChunk

invalid character %q after chunk size

Error message

invalid character %q after chunk size

What it means

After the hexadecimal chunk size, fasthttp permits either an optional space/tab (optional-whitespace separator) or a chunk extension starting with ';'. If a ';' appears AFTER whitespace was already seen, the framing is invalid per fasthttp's request-smuggling-hardening rules, so it returns ErrBrokenChunk with this message.

Source

Thrown at http.go:3007

		}
		// Security: Don't allow newlines in chunk extensions.
		// This can lead to request smuggling issues with some reverse proxies.
		if c == '\n' {
			return -1, ErrBrokenChunk{
				error: errors.New("invalid character '\\n' after chunk size"),
			}
		}
		if inExt {
			continue
		}
		switch c {
		case ' ', '\t':
			afterSizeOWS = true
			continue
		case ';':
			if afterSizeOWS {
				return -1, ErrBrokenChunk{
					error: fmt.Errorf("invalid character %q after chunk size", c),
				}
			}
			inExt = true
			continue
		default:
			return -1, ErrBrokenChunk{
				error: fmt.Errorf("invalid character %q after chunk size", c),
			}
		}
	}
	err = readCrLf(r)
	if err != nil {
		return -1, err
	}
	return n, nil
}

func readCrLf(r *bufio.Reader) error {

View on GitHub (pinned to c96f600972)

Solutions

  1. Fix the client/proxy to emit extensions directly after the size ("5;ext=1") with no space before ';'.
  2. Strip chunk extensions in the upstream producer; send a plain size line.
  3. If you own an intermediary, configure it to normalize chunked framing before forwarding.
  4. Drop the request as smuggling-suspect: handle ErrBrokenChunk and close the connection (fasthttp already does this).

Example fix

// before (wire format)
5 ;ext=1\r\nhello\r\n0\r\n\r\n
// after
5;ext=1\r\nhello\r\n0\r\n\r\n
Defensive patterns

Strategy: try-catch

Validate before calling

// Server-side: if you control ingress, reject chunk extensions after OWS
// with a pre-check proxy rule:
// deny requests whose chunk-size lines match /(^|\r\n)[0-9a-fA-F]+[ \t]+;/

Type guard

func isChunkExtAfterOWS(err error) bool {
    var bc fasthttp.ErrBrokenChunk
    return errors.As(err, &bc) &&
        strings.Contains(bc.error.Error(), "invalid character")
}

Try / catch

var bc fasthttp.ErrBrokenChunk
if errors.As(err, &bc) {
    // possible request-smuggling attempt: drop and close
    ctx.ConnectionClose()
    return
}

Prevention

When it happens

Trigger: A peer sends a chunk-size line like "5 ;ext=1" — i.e. chunk extension after an OWS separator. Rejected here to prevent request smuggling through reverse proxies.

Common situations: Requests forwarded through non-conforming proxies/clients that emit "size ;ext" chunk lines; hand-rolled HTTP clients or fuzzers; request-smuggling probe traffic.

Understand the failure class

Related errors


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