Change:
6. <del> "Datagram-Flow-Id" is a Item Structured Field STRUCT-FIELD.  Its value MUST be an Integer.  Its ABNF is: The "Datagram-Flow-Id" header field is used to associate a datagram flow identifier with an HTTP message.  For example, the definition of an HTTP method could instruct the client to use its flow identifier allocation service to allocate a new flow identifier, and then the client will add the "Datagram-Flow-Id" header field to its request to communicate that value to the server.  For example, the resulting header field could look like: Definitions of HTTP features that use the "Datagram-Flow-Id" header field MAY define their own parameters (parameters are defined in Section 3.1.2 of STRUCT-FIELD).  For example, an HTTP method that wishes to use two datagram flow identifiers for the lifetime of its request stream could encode the second flow identifier as a parameter, which could look like this: The "Datagram-Flow-Id" header field MUST NOT be present more than once on a given HTTP message; any HTTP message containing more than one "Datagram-Flow-Id" header field is malformed. Since the QUIC STREAM frame that contains the "Datagram-Flow-Id" header field could be lost or reordered, it is possible that an endpoint will receive an HTTP/3 datagram with a flow identifier that it does not know as it has not yet received the corresponding "Datagram-Flow-Id" header field.  Endpoints MUST NOT treat that as an error; they MUST either silently discard the datagram or buffer it until they receive the "Datagram-Flow-Id" header field. </del> <ins> "Datagram-Flow-Id" is a List Structured Field STRUCT-FIELD, whose members MUST all be Items of type Integer.  Its ABNF is: The "Datagram-Flow-Id" header field is used to associate one or more datagram flow identifiers with an HTTP message.  As a simple example using a single identifier, the definition of an HTTP method could instruct the client to use its flow identifier allocation service to allocate a new flow identifier, and then the client will add the "Datagram-Flow-Id" header field to its request to communicate that value to the server.  In this example, the resulting header field could look like: List members are flow identifier elements, which can be named or unnamed.  One element in the list is allowed to be unnamed, but all but one elements MUST carry a name.  The name of an element is encoded in the key of the first parameter of that element (parameters are defined in Section 3.1.2 of STRUCT-FIELD).  Each name MUST NOT appear more than once in the list.  The value of the first parameter of each named element (whose corresponding key conveys the element name) MUST be of type Boolean and equal to true.  The value of the first parameter of the unnamed element MUST NOT be of type Boolean. The ordering of the list does not carry any semantics.  For example, an HTTP method that wishes to use four datagram flow identifiers for the lifetime of its request stream could look like this: In this example, 42 is the unnamed flow identifier, 44 represents the name "ecn-ect0", 46 represents "ecn-ect1", and 48 represents "ecn- ce".  Note that, since the list ordering does not carry semantics, this example can be equivalently encoded as: Even if a sender attempts to communicate the meaning of a flow identifier before it uses it in an HTTP/3 datagram, it is possible that its peer will receive an HTTP/3 datagram with a flow identifier that it does not know as it has not yet received the corresponding "Datagram-Flow-Id" header field.  (For example, this could happen if the QUIC STREAM frame that contains the "Datagram-Flow-Id" header field is reordered and arrives afer the DATAGRAM frame.)  Endpoints MUST NOT treat that scenario as an error; they MUST either silently discard the datagram or buffer it until they receive the "Datagram- Flow-Id" header field. Distinct HTTP requests MAY refer to the same flow identifier in their respective "Datagram-Flow-Id" header fields. </ins> Note that integer structured fields can only encode values up to <del> 10^15-1, therefore the maximum possible value of the "Datagram-Flow- Id" header field is lower then the theoretical maximum value of a flow identifier which is 2^62-1 due to the QUIC variable length integer encoding.  If the flow identifier allocation service of an endpoint runs out of values lower than 10^15-1, the endpoint MUST treat is as a connection error of type H3_ID_ERROR. </del> <ins> 10^15-1, therefore the maximum possible value of an element of the "Datagram-Flow-Id" header field is lower then the theoretical maximum value of a flow identifier which is 2^62-1 due to the QUIC variable length integer encoding.  If the flow identifier allocation service of an endpoint runs out of values lower than 10^15-1, the endpoint MUST fail the flow identifier allocation.  An HTTP message that carries a "Datagram-Flow-Id" header field with a flow identifier value above 10^15-1 is malformed (see Section 8.1.2.6 of H2). </ins> 7.

Discussion:
This PR switches the header to a list on MT's suggestion to make the semantics clearer.
URL states: The text is a little ambiguous. I presume the intention is that the endpoint that is allocating flows should do what HTTP/3 defines as ? The doesn't cover the case where an endpoint receives a Datagram Flow ID greater than 10^15-1 (either in a request or a DATAGRAM). I think it might help to separate these cases. Receiving a value of 10^15-1 is always a connection error of type H3IDERROR. But I'm not so sure about the sender case, if you really are flow ID exhausted, perhaps it is nicer to just spin up a new connection and leave the current one as is. We might recommend that endpoints initiate an HTTP/3 graceful close followed by an application close - but reusing H3IDERROR for that case seems a bit overkill.
I don't think receiving a DATAGRAM whose flow ID is >= 10^15 is an error, the receiver should just silently drop it as the flow ID is unknown. Either way we should add text to clarify the expected action of the receiver. In the sender case, I agree with you when the sender is the client, because in that case the client should instead just spin up a separate connection. On the server sender however, there is no such escape hatch, so perhaps we should tell the server to fail the operation that requested the flow ID.
Sorry I was not specific in my comment. I meant to speak about receiving the header field e.g. That would lead to an SF Integer parsing error, which would cause the field to be ignored - unless we define different behaviour. Ignoring the header has an interesting interplay with the optional guidance to buffer it until they receive the "Datagram-Flow-Id" header. Ignoring things that are strictly above the known limits seems a little too generous. Is there a reason not to reject such requests and HTTP/3 DATAGRAMS?
Ah, in that case I agree - receipt of a Datagram-Flow-Id header with value >= 10^15 should cause a connection error of type H3IDERROR.

I was just thinking that conceptually receiving DATAGRAM with strange flow IDs should not be an error because that might lead implementors to declare than any unknown flow ID is an error which would break valid scenarios in the presence of reordering.
Yeah. However, I think it would be fine to reject such a request with an 4xx response rather than tear down the entire connection...
Fair enough, that works too. I'll just state that in that scenario the request is malformed
Section 6 makes the keen observation that: This is accurate but, when thinking about HTTP/3 APIs, does not cover all possible reasons that might cause a request message to be processed after the corresponding DATAGRAM frame is available. For instance, the message might be blocked by QPACK, or the implementation might present DATAGRAMS before stream headers. We could boil the ocean with describing all possible reasons, so I think it might be better to shuffle the text to focus on describe the symptom (DATAGRAMS before HTTP messages) and the treatment. We can then give non-exhaustive example(s) as already done.
I would prefer to not boil the ocean :) I'll make an editorial change to make it clearer that this is just an example among others.
The document currently uses the following example: Motivating this with an example of how to express multiple flow identifiers. I think that this example is potentially harmful. It implies a lot about a potential extension mechanism as part of an example, but does not commit to properly defining an extension. For examples like this I would much prefer to see something that is very clearly bogus. Otherwise, people might implement that to the point that they even achieve interoperability of a sort. For instance, the following requires a lot more guessing about how to interpret it, to the point that I would guess that pseudo-interoperability would be hard to arrive at by accident: See also .
The goal of this example was to show a way to build an extension. A full example of this being used is . I'm not really sure how to improve this, because making it clearly bogus defeats the purpose. Could you provide a PR?
Maybe we should talk more about the spelling of the ECN extension, which I haven't reviewed. I don't think that you should hide flow identifiers in this fashion.

It prevents an intermediary from understanding which requests are actively using flow identifiers. A gateway might need to know that in order to ensure that DATAGRAM frames are consistently forwarded to the right origin server. An alternative spelling that doesn't have that property would be:
To make sure I'm understand you correctly, are you suggesting a structured field list here? That would work, and actually in that case I'd suggest dropping the parameter on the first element to make this simpler.
Yep, that's it. And I considered the same. No parameter works fine.
It's not really clear whether there are any expectations in relation to cardinality of flow identifiers and the field. Can two fields refer to the same flow ID? Can the same request reference multiple flow IDs?
I think the h3 datagram draft should allow both: two requests can reuse the same flow ID if the definition of that HTTP features allows it (this feature is used by the ) one request can reference two flow IDs - I think this is already stated though:
I'm sure that people operating intermediaries might have something to say here. A gateway that routes flows might be unwilling to replicate datagram flows that are bound to requests that go to different origin servers. I agree that one request to many flows is worthwhile, but mention in examples doesn't really count as a specification.
Fair enough, I'll add text to make this clearer. And I'll add a note to the intermediaries section about how the intermediary needs to ensure that if a second request arrives that shares a flow ID with a previous one, the intermediary MUST either send the new request to the same backend or reject it.