cloudflare/quiche · error

Expected stream_send on stream

Error message

Expected stream_send on stream {} to write {} bytes, got {}

What it means

This panic comes from h3i's action validation when a script asserts that quiche's stream_send wrote an exact number of bytes, but it wrote a different amount. h3i executes scripted H3 actions against a connection and verifies each ExpectedStreamSendResult; a byte-count mismatch means the connection or stream state differed from what the script assumed (e.g. stream already closed, flow control limited the write). It is a test-harness assertion failure, not a runtime error you can catch in the library.

Solutions

  1. Print the actual bytes written and compare with the expected count; adjust the script's expected value or the payload size.
  2. Check the stream's available send capacity (flow control / stream state) before the action; add a wait or frame-action for the peer's MAX_STREAM_DATA/MAX_DATA update.
  3. If exact length doesn't matter, relax the assertion to ExpectedStreamSendResult::OkAny or just assert no error.

Example fix

// before
ExpectedStreamSendResult::OkExact(1200),
// after
ExpectedStreamSendResult::OkExact(written) // align with actual flow-control-limited write, or use OkAny
Defensive patterns

Strategy: validation

Validate before calling

// before executing the action
assert!(expected_bytes <= conn.stream_capacity(stream_id).unwrap_or(0),
        "stream {} cannot accept {} bytes", stream_id, expected_bytes);

Prevention

When it happens

Trigger: Executing an ExecuteAction with ExpectedStreamSendResult::OkExact(n) where quiche_conn_stream_send returns Ok(m) with m != n on the given stream_id.

Common situations: Scripts written against one server reused against another with different flow-control windows; sending on a stream that already had partial data buffered; stream capacity reduced by peer MAX_STREAM_DATA after the script was authored.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of cloudflare/quiche@9f96daa2c2 (2026-09-08). Data as JSON: /api/errors/cf718786ed221505. Report an issue: GitHub.

Appendix: source

Thrown at h3i/src/client/mod.rs:125

pub(crate) type StreamParserMap = HashMap<u64, FrameParser>;

fn validate_stream_send_result(
    result: quiche::Result<usize>, expected: &ExpectedStreamSendResult,
    stream_id: u64,
) {
    match expected {
        ExpectedStreamSendResult::Ok => {
            result.unwrap_or_else(|err| {
                panic!(
                    "Expected stream_send on stream {} to succeed, but got: {:?}",
                    stream_id, err
                )
            });
        },
        ExpectedStreamSendResult::OkExact(expected_bytes) => {
            match result {
                Ok(actual_bytes) if actual_bytes == *expected_bytes => {},
                Ok(actual_bytes) => panic!(
                    "Expected stream_send on stream {} to write {} bytes, got {}",
                    stream_id, expected_bytes, actual_bytes
                ),
                Err(err) => panic!(
                    "Expected stream_send on stream {} to write {} bytes, got error: {:?}",
                    stream_id, expected_bytes, err
                ),
            }
        },
        ExpectedStreamSendResult::Error(expected_err) => {
            match result {
                Ok(written) => panic!(
                    "Expected stream_send on stream {} to fail with {:?}, but wrote {} bytes",
                    stream_id, expected_err, written
                ),
                Err(actual_err) if &actual_err == expected_err => {},
                Err(actual_err) => panic!(
                    "Expected stream_send on stream {} to fail with {:?}, got {:?}",

View on GitHub (pinned to 9f96daa2c2)