valyala/fasthttp · error

invalid headers, headers cannot start with space or tab

Error message

invalid headers, headers cannot start with space or tab

What it means

The header scanner requires the first line of a header block to start a header name; if the buffer begins with a space or tab (an obsolete line fold with no preceding header), parsing fails with this error. next() raises it and it propagates through parseHeaders and parseTrailer.

Source

Thrown at headerscanner.go:52

			return false
		}

		if s.blockEnd >= 4 && s.blockEnd <= len(s.b) &&
			bytes.Equal(s.b[s.blockEnd-4:s.blockEnd], strCRLFCRLF) {
			// The caller already found the end of the block, no need to
			// search for it again. The first CRLFCRLF can only sit at
			// blockEnd-4 since readRawHeaders stops at the first blank line.
			s.b = s.b[:s.blockEnd]
		} else {
			i := bytes.Index(s.b, strCRLFCRLF)
			if i < 0 {
				s.err = ErrNeedMore
				return false
			}
			s.b = s.b[:i+4]
		}
		if len(s.b) > 0 && (s.b[0] == ' ' || s.b[0] == '\t') {
			s.err = errors.New("invalid headers, headers cannot start with space or tab")
			return false
		}

		s.initialized = true
	}

	kv, colon, err := s.readContinuedLineSlice()
	if len(kv) == 0 {
		s.err = err
		return false
	}

	// Key ends at the first colon, already found by readContinuedLineSlice.
	k, v := kv[:colon], kv[colon+1:]
	valid, innerSpace := isValidHeaderKey(k)
	if !valid {
		s.err = fmt.Errorf("malformed mime header line: %q", kv)
		return false

View on GitHub (pinned to c96f600972)

Solutions

  1. Fix the sender so each header line starts with 'Name: value' with no leading whitespace.
  2. If line folding is intentional, unfold headers before writing (join continuation lines into one).
  3. Sanitize/validate raw bytes at the edge proxy before forwarding to fasthttp.
  4. Update the client library — old versions of some HTTP stacks emitted obs-fold line endings.

Example fix

// before
"Host: example.com\r\n\r\n  X: y\r\n"
// after
"Host: example.com\r\nX: y\r\n"
Defensive patterns

Strategy: validation

Validate before calling

func headersWellFormed(raw []byte) bool {
    lines := strings.Split(string(raw), "\r\n")
    for _, l := range lines {
        if l == "" { break }
        if l[0] == ' ' || l[0] == '\t' { return false }
    }
    return true
}

Prevention

When it happens

Trigger: HeaderScanner.Next() on a header block whose first byte is ' ' or '\t' — e.g. a request/response whose headers start with a continuation line, or trailer section beginning with folded whitespace.

Common situations: Broken clients/servers emitting malformed folded headers; corruption from a hand-rolled HTTP writer; fuzzed or malicious input probing the parser.

Related errors


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