The http2 spec says:
A receiver MUST treat the receipt of a PUSH_PROMISE on a stream that is neither "open" nor "half-closed (local)" as a connection error (Section 5.4.1) of type PROTOCOL_ERROR. However, an endpoint that has sent RST_STREAM on the associated stream MUST handle PUSH_PROMISE frames that might have been created before the RST_STREAM frame is received and processed.
The spec also has this lifecycle diagram.
My understanding is that in order for a client to receive a
PUSH_PROMISE on a stream, the client must have <strong>all</strong> of these on that stream:
HEADERSframe (+ any
CONTINUATIONs) to the server</li> <li>not received
END_STREAMflag from the server</li> <li>not received
RST_STREAMframe from the server</li> </ul>
(Notably missing here is "not sent
RST_STREAM frame to the server”, which would lead to the stream being "closed"; the quote above says this is not grounds for connection error.)
In any case where these criteria are not met, then the client must treat receiving a PUSH_PROMISE as a connection error.
Is this a correct understanding?
Your understanding is correct.
The HTTP/2 protocol associates
PUSH_PROMISE streams to an existing stream, called the associated stream.
The associated stream must meet the conditions defined in the section of the specification quoted in the question; the bullet list in the question is another way of saying the same thing that the specification section says.