Skip to content

AsyncWrite reduces typed stream failures to io::ErrorKind::Other #353

Description

@spotdemo4

Version

h3 0.0.8, h3-webtransport 0.1.2

Platform

Linux desktop 7.1.7 NixOS x86_64 GNU/Linux

Summary

AsyncWrite loses top-level typed stream-error classification

Code Sample

use tokio::io::AsyncWriteExt;

// Arrange for the peer to reset/stop this stream, then write through the
// AsyncWrite adapter.
let err: std::io::Error = send.write_all(b"response").await.unwrap_err();
assert_eq!(err.kind(), std::io::ErrorKind::Other);

let typed = err
    .get_ref()
    .and_then(|source| source.downcast_ref::<h3::quic::StreamErrorIncoming>());
assert!(typed.is_some());

In contrast, polling the h3 trait directly returns the typed error:

let err = poll_fn(|cx| {
    h3::quic::SendStreamUnframed::poll_send(&mut send, cx, &mut bytes)
})
.await
.unwrap_err();

assert!(matches!(
    err,
    h3::quic::StreamErrorIncoming::StreamTerminated { .. }
));

Expected Behavior

The primary h3/WebTransport write path should preserve StreamErrorIncoming directly, or the I/O adapter should document a stable recovery API and provide useful error-kind mapping where possible.

Actual Behavior

BufRecvStream implements Tokio and futures AsyncWrite by converting every StreamErrorIncoming into:

std::io::Error::new(std::io::ErrorKind::Other, error)

The source object is not irretrievably discarded: callers can recover it by downcasting io::Error::get_ref(). However, the top-level type and meaningful ErrorKind classification are lost. Generic code that handles only io::ErrorKind cannot distinguish a peer stream reset from whole-connection loss.

Suggested upstream fix

Prefer typed h3 poll/future methods in public protocol APIs and make AsyncWrite an explicitly lossy compatibility adapter. If the adapter remains prominent, document source downcasting and map errors to meaningful io::ErrorKind values where semantics are unambiguous.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions