         XCTAssertNoThrow(try self.clientChannel.finish())
         XCTAssertNoThrow(try self.serverChannel.finish())
     }
+
+    func testFailingUnflushedWritesForGoaway() throws {
+        // Begin by getting the connection up.
+        try self.basicHTTP2Connection()
+
+        // Let's set up a stream.
+        let clientStreamID = HTTP2StreamID()
+        let headers = HTTPHeaders([(":path", "/"), (":method", "POST"), (":scheme", "https"), (":authority", "localhost")])
+        let reqFrame = HTTP2Frame(streamID: clientStreamID, payload: .headers(headers))
+        try self.assertFramesRoundTrip(frames: [reqFrame], sender: self.clientChannel, receiver: self.serverChannel)
+
+        // Now we're going to queue up a DATA frame.
+        var requestBody = self.clientChannel.allocator.buffer(capacity: 128)
+        requestBody.write(bytes: Array(repeating: UInt8(0x04), count: 128))
+        let reqBodyFrame = HTTP2Frame(streamID: clientStreamID, payload: .data(.byteBuffer(requestBody)))
+
+        var writeError: Error?
+        self.clientChannel.write(reqBodyFrame).whenFailure {
+            writeError = $0
+        }
+        XCTAssertNil(writeError)
+
+        // From the server side, we're going to send and deliver a GOAWAY frame. The client should receive this
+        // frame. The pending write will not be failed because it has not yet been flushed.
+        let frame = HTTP2Frame(streamID: .rootStream, payload: .goAway(lastStreamID: .rootStream, errorCode: .inadequateSecurity, opaqueData: nil))
+        try self.assertFramesRoundTrip(frames: [frame], sender: self.serverChannel, receiver: self.clientChannel)
+        XCTAssertNil(writeError)
+
+        // When we now flush the write, that write should fail immediately.
+        self.clientChannel.flush()
+        XCTAssertEqual(writeError as? NIOHTTP2Errors.NoSuchStream, NIOHTTP2Errors.NoSuchStream(streamID: clientStreamID))
+
+        // No other frames should be emitted.
+        self.clientChannel.assertNoFramesReceived()
+        self.serverChannel.assertNoFramesReceived()
+        XCTAssertNoThrow(try self.clientChannel.finish())
+        XCTAssertNoThrow(try self.serverChannel.finish())
+    }
+
+    func testFailingFlushedWritesForGoaway() throws {
+        // Begin by getting the connection up.
+        try self.basicHTTP2Connection()
+
+        // Install a reset handler.
+        XCTAssertNoThrow(try self.serverChannel.pipeline.add(handler: InstaGoawayHandler()).wait())
+
+        // Let's set up a stream.
+        let clientStreamID = HTTP2StreamID()
+        let headers = HTTPHeaders([(":path", "/"), (":method", "POST"), (":scheme", "https"), (":authority", "localhost")])
+        let reqFrame = HTTP2Frame(streamID: clientStreamID, payload: .headers(headers))
+        var requestBody = self.clientChannel.allocator.buffer(capacity: 1024)
+        requestBody.write(bytes: Array(repeating: UInt8(0x04), count: 1024))
+        let reqBodyFrame = HTTP2Frame(streamID: clientStreamID, payload: .data(.byteBuffer(requestBody)))
+
+        // We'll send some frames: specifically, a headers and 80kB of DATA.
+        // We do this to ensure that the DATA does not all go out to the network in one go, such that there is still
+        // some sitting in the pipeline when the RST_STREAM frame arrives. The last write will have a promise attached.
+        var writeError: Error?
+        self.clientChannel.write(reqFrame, promise: nil)
+        for _ in 0..<79 {
+            self.clientChannel.write(reqBodyFrame, promise: nil)
+        }
+
+        self.clientChannel.writeAndFlush(reqBodyFrame).whenFailure {
+            writeError = $0
+        }
+        XCTAssertNil(writeError)
+
+        // Let the channels dance. The GOAWAY should come through.
+        self.interactInMemory(self.clientChannel, self.serverChannel)
+        try self.clientChannel.assertReceivedFrame().assertGoAwayFrame(lastStreamID: 0, errorCode: UInt32(http2ErrorCode: HTTP2ErrorCode.inadequateSecurity), opaqueData: nil)
+
+        // The data frame write should have exploded. nghttp2 synthesises a "refusedStream" error code for this.
+        XCTAssertEqual(writeError as? NIOHTTP2Errors.StreamClosed, NIOHTTP2Errors.StreamClosed(streamID: clientStreamID, errorCode: .refusedStream))
+
+        // No other frames should be emitted.
+        self.clientChannel.assertNoFramesReceived()
+        self.serverChannel.assertNoFramesReceived()
+        XCTAssertNoThrow(try self.clientChannel.finish())
+        XCTAssertNoThrow(try self.serverChannel.finish())
+    }
 }

        let frame = self.unwrapInboundIn(data)
        if case .headers = frame.payload {
            let kaboomFrame = HTTP2Frame(streamID: frame.streamID, payload: .rstStream(.refusedStream))
            ctx.writeAndFlush(self.wrapOutboundOut(kaboomFrame), promise: nil)
        }
    }

    }
}

/// A channel handler that forcibly resets all inbound HEADERS frames it receives.
final class InstaResetHandler: ChannelInboundHandler {
    typealias InboundIn = HTTP2Frame
    typealias OutboundOut = HTTP2Frame
