Code change:
"Hypertext Transfer Protocol (HTTP) Field Name Registry" registry maintained at <https://www.iana.org/assignments/http-fields/>. <del> Just as in HTTP/1.x, field names are strings of ASCII characters that are compared in a case-insensitive fashion.  Field names MUST be converted to lowercase prior to their encoding in HTTP/2.  A request or response containing uppercase header field names MUST be treated as malformed. </del> <ins> Field names are strings of ASCII characters that are compared in a case-insensitive fashion.  Field names MUST be converted to lowercase when constructing a HTTP/2 message.  A request or response containing an uppercase character ('A' to 'Z', ASCII 0x41 to 0x5a) in a field name MUST be treated as malformed. HPACK is capable of carrying field names or values that are not valid in HTTP.  Though HPACK can carry any octet, fields are not valid in the following cases: A request or response that contains a field that violates any of these conditions MUST be treated as malformed.  In particular, an intermediary that does not process fields when forwarding messages MUST NOT forward fields that contain any of the values that are listed as prohibited above. Field values that are not valid according to the definition of the corresponding field do not cause a request to be malformed except as defined by the processing rules for the field. </ins> 8.1.2.1.

Related discussion:
text: Many Implementations will ultimately end up double validating field names: once to exclude the s in their h2 layer and then later in their semantic layer to include only the s. Double validation could be avoided if this document either didn't restrict field validity or precisely defined valid fields as a subset of s so that semantic layers could trust the fields received from their h2 layers as being valid HTTP. Maybe there is a reason for this double validation and the resulting CPU cycles, but I have yet to see why validity is only partially defined.
It suggests it but does not require it. The other text requires validation. Most intermediaries will not apply the full ABNF validation because a) it requires perfect understanding of the ABNF of all header fields, which they will not have, and b) even if they did, the -semantics ABNF is sufficiently costly to validate that they won't do it. Cheaper validation steps are more likely to be implemented. This document (and -semantics) is imprecisely defining them because a . The ABNF you're citing represents, fundamentally, guidance. If you want to reject things that don't conform to the ABNF you are free to do so (as -semantics says), but there is no document that obligates you to reject them. This is deliberate, because there is (IMO) absolutely no point in adding normative requirements that, if followed, would harm interoperability. In this case the document is calling out specific cases that MUST be rejected. Practically speaking the intention of this is to encode requirements from other messaging formats, such as -messaging, to ensure that HTTP/2 implementations do not encode header fields that cannot be safely translated to HTTP/1.1. This provides a lower bound on validation: so long as everybody does this, we can safely rely on HTTP/2 messages being represented in HTTP/1.1's framing. Note that this doesn't meant they'll be valid HTTP/1.1 messages, just that they are not going to parse incorrectly. With that in mind, the constraints added here are, in order: A cheap bitwise check that can be safely vectorised and applied to reject most invalid field names. This is sufficient to get close to the ABNF, but is cheaper. A check that reserves pseudo-headers and is a single-byte comparison.