tonhowtf/omniget · error
Unexpected relay response
Error message
Unexpected relay response: {} What it means
download() reads a line from the relay server after connecting and expects exactly "READY"; check_relay_error already filtered explicit relay error lines. Any other line means the relay/sender protocol is out of sync (or an empty/garbage line arrived), so download aborts with this message echoing the raw response.
Solutions
- Verify the relay server version matches the client's relay protocol (READY handshake).
- Log the raw response and check for an empty line — usually means the relay socket closed; retry the connection.
- Check check_relay_error's recognized error lines; extend it if the relay has new error strings so they surface as real errors instead of this generic bail.
- Retry the download; transient relay state can produce a premature non-READY line.
Example fix
// before
let response = read_line(&mut reader).await?;
check_relay_error(&response)?;
if response != "READY" { anyhow::bail!("Unexpected relay response: {}", response); }
// after
let response = read_line(&mut reader).await?;
if response.trim().is_empty() {
anyhow::bail!("Relay closed connection before READY; retrying");
}
check_relay_error(&response)?;
if response != "READY" { anyhow::bail!("Unexpected relay response: {:?}", response); } Defensive patterns
Strategy: retry
Validate before calling
let md = tokio::fs::metadata(&output_path).await?; // ensure output dir writable before connecting
if !output_dir_is_writable { anyhow::bail!("Output directory not writable"); } Try / catch
match download(opts).await {
Err(e) if e.to_string().contains("Unexpected relay response") => {
log::warn!("relay desync: {e}; retrying once");
download(opts).await?; // retry with fresh connection
}
other => other?,
} Prevention
- Keep relay server and client protocol versions in lockstep.
- Log raw relay lines with {:?} in development to catch desyncs early.
- Add a read timeout around read_line so a dead relay fails fast instead of returning empty lines.
- Extend check_relay_error whenever the relay adds new error strings.
When it happens
Trigger: Relay replies with a line other than "READY" after check_relay_error passes — e.g. an empty line from a closed relay connection, a protocol version mismatch, or the sender never completed handshake so the relay sent something else.
Common situations: Relay server version differs from the client (old relay sends "OK" or blank), sender dropped out between connection and READY, or a proxy/load balancer injected an HTTP error page as a line.
Related errors
- Relay closed connection unexpectedly
- Relay error
- Relay closed connection unexpectedly
- Relay error
- Unexpected relay response
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/837e2b729e6bb7ce.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/platforms/p2p/mod.rs:135
.ok_or_else(|| anyhow!("Invalid P2P URL"))?;
let _ = progress.send(ProgressUpdate::percent(-2.0)).await;
tracing::info!("[p2p] connecting to relay for code: {}", code);
let stream = connect_relay().await?;
let (read_half, mut write_half) = tokio::io::split(stream);
let mut reader = BufReader::new(read_half);
write_half
.write_all(format!("RECV {}\n", code).as_bytes())
.await?;
write_half.flush().await?;
let response = read_line(&mut reader).await?;
check_relay_error(&response)?;
if response != "READY" {
anyhow::bail!("Unexpected relay response: {}", response);
}
tracing::info!("[p2p] connected to sender via relay");
let file_name = read_line(&mut reader).await?;
let file_size_str = read_line(&mut reader).await?;
let file_size: u64 = file_size_str
.parse()
.map_err(|_| anyhow!("Invalid file size from sender: {}", file_size_str))?;
tracing::info!("[p2p] receiving: {} ({} bytes)", file_name, file_size);
write_half.write_all(b"OK\n").await?;
write_half.flush().await?;
let _ = progress.send(ProgressUpdate::percent(0.0)).await;
let sanitized = sanitize_filename::sanitize(&file_name);View on GitHub (pinned to 8600b91f42)