How to Open a Uni-Directional QUIC Stream in Iroh

Open a uni-directional QUIC stream in Iroh by calling conn.open_uni().await? on an established Connection, which returns a SendStream that supports only write operations.

Iroh provides an ergonomic QUIC abstraction built on the noq crate that simplifies working with uni-directional streams for one-way data transmission. Learning how to open a uni-directional QUIC stream in Iroh is essential for implementing fire-and-forget messaging patterns or sending requests without expecting immediate responses. This article walks through the implementation details found in the n0-computer/iroh repository, including concrete examples from the production codebase.

Understanding Uni-Directional QUIC Streams in Iroh

Uni-directional streams in Iroh are send-only channels that allow data transmission in a single direction. Once opened, these streams support write operations but explicitly disallow reads, making them ideal for scenarios where you need to push data to a peer without awaiting a response.

The underlying implementation delegates to the Noq connection's open_uni() method, wrapped in Iroh's high-level Connection API.

Opening a Send-Only Stream with open_uni()

In iroh/src/endpoint/connection.rs at lines 874-875, the Connection struct exposes the open_uni() method:

let mut send_stream = conn.open_uni().await?;

This async call returns an OpenUni<'_> future that resolves to a quic::SendStream. The method signature defined in iroh/src/endpoint/connection.rs forwards the request to the internal Noq connection, providing a standardized interface for stream creation.

Error Handling Patterns

Iroh's codebase demonstrates consistent error handling when opening uni-directional streams. The .anyerr() method converts underlying QUIC errors into the crate's unified error type:

let mut stream = conn.open_uni().await.anyerr()?;

For operations requiring additional diagnostic context, use .std_context():

let mut stream = conn.open_uni().await.std_context("failed to open uni stream")?;

Both patterns appear throughout the test suite and production code in iroh/src/endpoint.rs (lines 2115-2133 and 2362-2364), ensuring that stream creation failures provide actionable error messages.

Real-World Implementation Examples

Client Connections in Examples

The file iroh/examples/remote-info.rs at line 68 demonstrates a practical implementation:

let mut stream = conn.open_uni().await.anyerr()?;

This pattern appears after establishing a connection and before transmitting remote node information, showing the standard workflow for application developers.

Internal Socket Abstraction

In iroh/src/socket.rs at line 2859, the codebase uses a direct unwrap when success is guaranteed by surrounding logic:

let mut stream = conn.open_uni().await.unwrap();

This internal usage demonstrates that while application code should handle errors explicitly, Iroh's own socket implementation may use .unwrap() in controlled contexts where prior validation ensures the connection remains active.

Endpoint Management

The iroh/src/endpoint.rs file contains multiple references to open_uni() in complex scenarios involving multiplexed streams and connection management. These implementations show the pattern integrated into larger async workflows:

let mut send = conn.open_uni().await.anyerr()?;

These call sites demonstrate how uni-directional streams fit into Iroh's broader QUIC endpoint architecture, particularly when managing concurrent stream operations.

Summary

  • Single async call: Use conn.open_uni().await? to create a uni-directional stream from any active Connection.
  • Write-only semantics: The resulting SendStream supports only write operations, making it suitable for one-way data transmission.
  • Source location: The method is defined in iroh/src/endpoint/connection.rs at lines 874-875.
  • Error handling: Convert errors using .anyerr()? for standard Iroh error types or .std_context() for custom messages.
  • Usage patterns: Examples appear in iroh/examples/remote-info.rs (line 68) and iroh/src/socket.rs (line 2859).

Frequently Asked Questions

What is the difference between uni-directional and bi-directional streams in Iroh?

Uni-directional streams, created with open_uni(), are send-only and do not support reading data from the peer, making them ideal for fire-and-forget messages. Bi-directional streams allow both reading and writing, typically used for request-response patterns where data must flow in both directions.

How do I handle errors when opening a uni-directional stream?

The open_uni() method returns a Result that you should handle using Iroh's error conversion utilities. Call .anyerr()? to convert to the standard Iroh error type, or use .std_context("message")? to add descriptive context before propagating the error.

Can I read from a stream opened with open_uni()?

No. The SendStream returned by open_uni() is strictly write-only. Attempting to read from this stream type will fail at compile time because the type does not implement read methods. Use bi-directional streams if you need to receive data from the peer.

Where is the open_uni() method defined in the Iroh source code?

The method is defined on the Connection struct in iroh/src/endpoint/connection.rs at lines 874-875. According to the n0-computer/iroh source code, this implementation forwards the call to the underlying Noq connection's open_uni() method while integrating with Iroh's error handling and async runtime.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →