Change:
if it received a Version Negotiation packet that listed the versions in the server's Other Versions field, plus the negotiated version. If the client would have selected a different version, the client <del> MUST close the connection with a version negotiation error.  This connection closure prevents an attacker from being able to use forged Version Negotiation packets to force a version downgrade. </del> <ins> MUST close the connection with a version negotiation error.  In particular, if the client reacted to a Version Negotiation packet and the server's Other Versions field is empty, the client MUST close the connection with a version negotiation error.  These connection closures prevent an attacker from being able to use forged Version Negotiation packets to force a version downgrade. </ins> This validation of Other Versions is not sufficient to prevent downgrade.  Downgrade prevention also depends on the client ignoring

Discussion:
Q1) Other Versions can be empty. In that case, should validation fail? Q2) What does this "negotiated version" refer to? (I guess "it selects a mutually supported version and sends a new first flight with that version") Q3) Why don't we check Chosen Version at all?
Q1: correct. I've written to make that explicit in the spec. Q2: the term "negotiated version" is defined in Sections 4.2 and 4.3 Q3: see
Relating to Q3. is about compatible nego. I'm asking the case of incompatible nego here.
Chosen Version is used to pick the version in both compatible and incompatible VNs, and also when the server uses the version that the client started with.
OK. So, I feel that the following sentence should include something like "Chosen Version MUST be checked .... If a mismatch is found, the connection MUST be closed with VERSIONNEGOTIATIONERROR".
NAME since you were the motivation to replace verification with negotiation, do you have thoughts here? NAME points out that when implementing this the client needs to pick the new version based on long headers before it sees the transport parameters
I think that "negotiated" is correct in this context (incompatible) even though it is really just the client selecting from a list, that's still negotiating a version (for which the outcome is a negotiated version). Christian is right about the process, but that doesn't mean we can't call it negotiation. The process is negotiation. The transport parameter captures the outcome of that URL the information necessary to validate that outcome. If we hadn't named the Version Negotiation packet something else, we might have more flexibility in how things are named [^1], but that's a done deal. [^1]: Well, I guess we'd have the same amount of flexibility, except with different words.
I am a bit puzzled here. Suppose that the client started with version 1, is receiving the transport parameters with chosen version X in handshake packet of version Y. There are four possible combination. My understanding is that only two are correct. handshake  selected version 2 -----------------------: ----------- version 1 error version 2 correct Am I wrong?

NAME that will depend on how the QUICv2 draft defines compatible VN from v1 to v2. I think we should define it in such a way that makes your table correct, but that's a design topic for that draft.
I understand that it is pretty hard to reason about this in the abstract, but I do believe that we could have some kind of invariant specification here. The basic idea is that we will have: a client flight in which the client uses version A and proposes version B (and maybe C and D) a negotiation happening when the server parses the transport parameters (or equivalent) received in the first flight and selects version B or remains with A a server flight in which packets are carried as specified in version A or B. The invariant matrix would be: packet header  selected version B --: -- version A error version B correct I would expect that the "erroneous" combinations result in a Version negotiation error.
I don't think we have invariants for this. For example, you had proposed that the server might have a first flight of ACKs in version A until it can parse the entire ClientHello. I don't think there's value in being prescriptive here, any invariant we come up with will rely on assumptions that might be broken by future versions of QUIC.
Maybe what we want is some kind of guidelines on what reprocessing means, and the implication on packet parsing, etc. In any case, the server will transition from sending version A to sending version B. If version B is somehow preferred, we want that to happen before the handshake is complete. Both Kazu & I had to work this out for V1->V2, which makes me think some kind of guide will be useful. Maybe under the heading of "implementation experience".
That makes sense. I'm closing this issue in favor of URL since that's where the transition is defined.