{"record":{"id":"bfdc032ab9ace71e","repo":"tonhowtf/omniget","slug":"failed-to-connect-to-relay-mod","errorCode":null,"errorMessage":"Failed to connect to relay {}: {}","messagePattern":"Failed to connect to relay (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/platforms/p2p/mod.rs","lineNumber":32,"sourceCode":"\nuse crate::models::media::{DownloadOptions, DownloadResult, MediaInfo, MediaType, VideoQuality};\nuse crate::platforms::traits::PlatformDownloader;\n\nconst CHUNK_SIZE: usize = 64 * 1024;\n\nfn relay_addr() -> String {\n    std::env::var(\"OMNIGET_RELAY\").unwrap_or_else(|_| \"relay.tonho.wtf:9009\".to_string())\n}\n\nasync fn connect_relay() -> anyhow::Result<TcpStream> {\n    let addr = relay_addr();\n    let stream = tokio::time::timeout(\n        std::time::Duration::from_secs(10),\n        TcpStream::connect(&addr),\n    )\n    .await\n    .map_err(|_| anyhow!(\"Connection to relay timed out (10s)\"))?\n    .map_err(|e| anyhow!(\"Failed to connect to relay {}: {}\", addr, e))?;\n    Ok(stream)\n}\n\nasync fn read_line(\n    reader: &mut BufReader<tokio::io::ReadHalf<TcpStream>>,\n) -> anyhow::Result<String> {\n    let mut line = String::new();\n    let n = reader.read_line(&mut line).await?;\n    if n == 0 {\n        anyhow::bail!(\"Relay closed connection unexpectedly\");\n    }\n    Ok(line.trim_end().to_string())\n}\n\nfn check_relay_error(line: &str) -> anyhow::Result<()> {\n    if let Some(err) = line.strip_prefix(\"ERROR \") {\n        anyhow::bail!(\"Relay error: {}\", err);\n    }","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/platforms/p2p/mod.rs#L14-L50","documentation":"connect_relay surfaces the underlying OS error when TcpStream::connect to the relay fails immediately (the message interpolates the relay address and the io::Error). This is the non-timeout failure path: the connect attempt itself returned an error, e.g. connection refused, DNS resolution failure, or no route to host.","triggerScenarios":"TcpStream::connect(&addr) returns Err — relay port not listening (connection refused), hostname in relay_addr() does not resolve, or OS-level network error (no route, network unreachable).","commonSituations":"Relay service not started on the host; typo in relay host/port; DNS outage; connecting to localhost relay that isn't running; wrong port after a config change.","solutions":["Read the embedded io::Error: 'refused' means start the relay service; 'resolve' means fix DNS/hostname in relay_addr().","Confirm the relay is listening on the configured port (ss -ltn / netstat on the relay host).","Validate relay_addr() output and correct any misconfigured host or port.","Test connectivity manually: nc -vz <relay-host> <port>.","Retry if the failure was transient (network flap); consider adding automatic retry in the caller."],"exampleFix":"// before\n.map_err(|e| anyhow!(\"Failed to connect to relay {}: {}\", addr, e))?;\n// after\n.map_err(|e| {\n    tracing::error!(\"relay connect failed addr={} err={:?}\", addr, e);\n    anyhow!(\"Failed to connect to relay {}: {} (is the relay running and reachable?)\", addr, e)\n})?;","handlingStrategy":"retry","validationCode":"// Rust: probe the relay endpoint before the transfer\nasync fn can_reach_relay(addr: &str) -> Result<(), String> {\n    tokio::net::TcpStream::connect(addr)\n        .await\n        .map(|_| ())\n        .map_err(|e| format!(\"relay {} unreachable: {}\", addr, e))\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = connect_relay().await {\n    tracing::error!(\"relay connect failed: {e:#}\");\n    // parse embedded io::Error kind: ConnectionRefused -> start relay; NotFound/Resolve -> fix DNS\n    return Err(anyhow!(\"Relay unavailable, please try again later\"));\n}","preventionTips":["Run the relay under a process manager so it auto-restarts","Validate relay_addr() config at app startup with a connectivity check","Use IPs or verified DNS names to avoid resolution failures","Log the io::Error kind, not just the message"],"tags":["network","tcp","connection","p2p"],"backgroundTag":"connection-refused","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}