`AsyncWrite` reduces typed stream failures to `io::ErrorKind::Other`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 890
- Forks
- 136
- Avg merge
- 14d 20h
- Merged PRs (30d)
- 2
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the BufRecvStream Tokio and futures AsyncWrite implementations described in the issue, and reproduce the error using the provided write_all example. Compare that behavior with the direct SendStreamUnframed::poll_send path. Done would require an agreed design for preserving or documenting StreamErrorIncoming and for mapping errors, plus tests covering peer stream termination and connection loss.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100