{"record":{"id":"92e06f895207c307","repo":"tonhowtf/omniget","slug":"relay-error-mod","errorCode":null,"errorMessage":"Relay error: {}","messagePattern":"Relay error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/platforms/p2p/mod.rs","lineNumber":49,"sourceCode":"    .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    }\n    Ok(())\n}\n\npub struct P2pDownloader;\n\nimpl P2pDownloader {\n    pub fn new() -> Self {\n        Self\n    }\n}\n\n#[async_trait]\nimpl PlatformDownloader for P2pDownloader {\n    fn name(&self) -> &str {\n        \"p2p\"\n    }\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/platforms/p2p/mod.rs#L31-L67","documentation":"The P2P relay protocol signals failures by sending a line prefixed with 'ERROR '. check_relay_error parses that prefix and converts the remainder into an anyhow error with this message. It surfaces server-side rejections of the client's protocol commands.","triggerScenarios":"Any relay response line beginning with \"ERROR \" — e.g. the relay rejected a JOIN/registration, room is full, peer not found, or the requested code is unknown.","commonSituations":"Connecting to a relay with a different protocol version; using a share code whose room no longer exists on the relay; relay rejecting unauthenticated peers; sending commands out of order.","solutions":["Read the relay's message embedded in the error to see the specific rejection","Verify client and relay protocol versions match","Re-register/join the relay room before sending data commands","Check relay server logs for why the command was rejected"],"exampleFix":"// before\nlet resp = read_line(&mut reader).await?;\ncheck_relay_error(&resp)?;\n// after\nlet resp = read_line(&mut reader).await?;\nif let Err(e) = check_relay_error(&resp) {\n    tracing::warn!(\"relay rejected command, response={:?}\", resp);\n    return Err(e.context(\"relay rejected our request; verify code and protocol version\"));\n}","handlingStrategy":"try-catch","validationCode":"// before each command, ensure the relay session is registered\nanyhow::ensure!(joined_room.load(Ordering::SeqCst), \"not joined to relay room\");","typeGuard":null,"tryCatchPattern":"let resp = read_line(&mut reader).await?;\nif let Err(e) = check_relay_error(&resp) {\n    error!(\"relay said: {} — response: {:?}\", e, resp);\n    return Err(e);\n}","preventionTips":["Log the full relay response line before bailing","Keep client/relay protocol versions in sync","Re-join rooms after relay restarts"],"tags":["network","p2p","relay","protocol"],"backgroundTag":"api-error-response","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"}