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

  1. Retry the connection to the relay with backoff if the transfer is resumable.
  2. Check that the relay service is running and reachable (relay address/port correct, process alive).
  3. Add TCP keepalive / application-level heartbeat so idle hops are not silently dropped by NAT.
  4. Log the transfer stage at EOF to see which protocol step lost the connection and handle partial-transfer cleanup.
  5. 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

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


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)