{"record":{"id":"d71e66acc864c201","repo":"shadowsocks/shadowsocks-rust","slug":"unexpected-response-from-http-detectportal-firef","errorCode":null,"errorMessage":"unexpected response from http://detectportal.firefox.com/success.txt, {:?}","messagePattern":"unexpected response from http://detectportal\\.firefox\\.com/success\\.txt, (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/shadowsocks-service/src/local/loadbalancing/ping_balancer.rs","lineNumber":914,"sourceCode":"            &addr,\n            self.server.connect_opts_ref(),\n        )\n        .await?;\n        stream.write_all(GET_BODY).await?;\n\n        let mut reader = BufReader::new(stream);\n\n        let mut buf = Vec::new();\n        reader.read_until(b'\\n', &mut buf).await?;\n\n        let mut headers = [httparse::EMPTY_HEADER; 1];\n        let mut response = httparse::Response::new(&mut headers);\n\n        if response.parse(&buf).is_ok() && matches!(response.code, Some(200) | Some(204)) {\n            return Ok(());\n        }\n\n        Err(Error::new(\n            ErrorKind::InvalidData,\n            format!(\n                \"unexpected response from http://detectportal.firefox.com/success.txt, {:?}\",\n                ByteStr::new(&buf)\n            ),\n        ))\n    }\n\n    async fn check_request_udp(&self) -> io::Result<()> {\n        // TransactionID: 0x1234\n        // Flags: 0x0100 RD\n        // Questions: 0x0001\n        // Answer RRs: 0x0000\n        // Authority RRs: 0x0000\n        // Additional RRs: 0x0000\n        // Queries\n        //    - QNAME: \\x07 firefox \\x03 com \\x00\n        //    - QTYPE: 0x0001 A","sourceCodeStart":896,"sourceCodeEnd":932,"githubUrl":"https://github.com/shadowsocks/shadowsocks-rust/blob/8eb0f0a65b1d976ab6bed5787327ef86529b0435/crates/shadowsocks-service/src/local/loadbalancing/ping_balancer.rs#L896-L932","documentation":"check_request_tcp_firefox probes a candidate proxy by requesting http://detectportal.firefox.com/success.txt and accepts 200 or 204. When the response cannot be parsed by httparse or the status code is neither 200 nor 204, the library concludes the proxy path is unusable and throws InvalidData including the raw bytes received.","triggerScenarios":"Calling check_request (which dispatches to check_request_tcp_firefox) when the proxy returns non-HTTP data, an error/redirect page, or truncated output for the success.txt probe.","commonSituations":"Captive portals returning their login page instead of success.txt, blocked detectportal.firefox.com on the server side, dead proxy nodes, or misconfigured DNS on the remote server.","solutions":["Test the failing proxy node manually; replace or remove it from the server list if it cannot relay traffic.","Check for captive-portal or ISP interception rewriting the probe response.","Ensure the remote server can reach detectportal.firefox.com (DNS + egress).","Use the chromium 204 probe or a custom check URL if this host is unreliable in your environment."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// precheck reachability of the probe host through an alternate path\n// if detectportal.firefox.com is blocked locally, probe results are unreliable","typeGuard":null,"tryCatchPattern":"if let Err(e) = check_request(&server).await {\n    if e.kind() == std::io::ErrorKind::InvalidData {\n        // mark server unhealthy instead of aborting the balancer\n        server.set_score(...); schedule_recheck(&server);\n    }\n}","preventionTips":["Run both firefox and chromium probes so one blocked host doesn't disqualify good nodes","Watch for captive-portal networks (hotel/airport Wi-Fi) where probes always fail","Keep the balancer in LivenessCheckMode so failing nodes re-check instead of being dropped permanently"],"tags":["network","proxy","health-check","http"],"backgroundTag":"http-error-response","analyzedSha":"8eb0f0a65b1d976ab6bed5787327ef86529b0435","analyzedAt":"2026-09-09T12:20:43.168Z","contentChangedAt":"2026-09-09T12:20:43.168Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}