tonhowtf/omniget · error
Relay closed connection unexpectedly
Error message
Relay closed connection unexpectedly
What it means
p2p.rs throws this in read_line() when the TCP read from the relay returns 0 bytes, i.e. the relay closed the connection (EOF) while a line was still expected. It guards against a peer/relay disappearing mid-protocol, converting tokio's silent EOF into an explicit error.
Solutions
- Retry the connection to the relay with backoff if the transfer is resumable.
- Check that the relay service is running and reachable (relay address/port correct, process alive).
- Add TCP keepalive / application-level heartbeat so idle hops are not silently dropped by NAT.
- Log the transfer stage at EOF to see which protocol step lost the connection and handle partial-transfer cleanup.
- If the relay closes immediately, check relay-side logs for authentication or protocol-version rejections.
Example fix
// before
let line = read_line(&mut reader).await?;
// after
let line = match read_line(&mut reader).await {
Ok(l) => l,
Err(e) if e.to_string() == "Relay closed connection unexpectedly" => {
warn!("relay dropped connection; reconnecting (attempt {})...", n);
reconnect_and_resume().await?;
continue;
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: retry
Validate before calling
// probe the relay before the transfer let mut probe = TcpStream::connect(relay_addr).await?; // fail fast if relay is down
Try / catch
match read_line(&mut reader).await {
Err(e) if e.to_string() == "Relay closed connection unexpectedly" => reconnect_with_backoff().await,
other => other,
} Prevention
- Enable TCP keepalive on relay connections
- Add application-level heartbeats to survive NAT idle timeouts
- Monitor relay process health and restart it automatically
- Persist transfer progress so reconnects can resume
When it happens
Trigger: Any call to read_line() where reader.read_line(&mut line).await? returns n == 0 — relay process stopped, network dropped, relay timed out the connection, or the sender/receiver closed the socket early. Called from both download and run_sender.
Common situations: Relay server restarted or crashed mid-transfer; NAT/firewall idle timeout dropped the TCP connection; remote peer quit the transfer; unstable network (Wi-Fi/mobile) between client and relay.
Related errors
- Relay closed connection unexpectedly
- Relay error
- Relay error
- Unexpected relay response
- Connection to relay timed out (10s)
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/12049dd505ac04c7.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/platforms/p2p.rs:40
async fn connect_relay() -> anyhow::Result<TcpStream> {
let addr = relay_addr();
let stream = tokio::time::timeout(
std::time::Duration::from_secs(10),
TcpStream::connect(&addr),
)
.await
.map_err(|_| anyhow!("Connection to relay timed out (10s)"))?
.map_err(|e| anyhow!("Failed to connect to relay {}: {}", addr, e))?;
Ok(stream)
}
async fn read_line(
reader: &mut BufReader<tokio::io::ReadHalf<TcpStream>>,
) -> anyhow::Result<String> {
let mut line = String::new();
let n = reader.read_line(&mut line).await?;
if n == 0 {
anyhow::bail!("Relay closed connection unexpectedly");
}
Ok(line.trim_end().to_string())
}
fn check_relay_error(line: &str) -> anyhow::Result<()> {
if let Some(err) = line.strip_prefix("ERROR ") {
anyhow::bail!("Relay error: {}", err);
}
Ok(())
}
pub struct P2pDownloader;
impl P2pDownloader {
pub fn new() -> Self {
Self
}
}View on GitHub (pinned to 8600b91f42)