{"record":{"id":"6dc0a909ecd73b78","repo":"tursodatabase/turso","slug":"invalid-request-line","errorCode":null,"errorMessage":"Invalid request line","messagePattern":"Invalid request line","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"cli/sync_server.rs","lineNumber":1179,"sourceCode":"            let value = line.split(':').nth(1)?.trim();\n            return value.parse().ok();\n        }\n    }\n    None\n}\n\nfn parse_http_request(data: &[u8]) -> Result<(String, String, Vec<u8>)> {\n    let header_end = find_header_end(data, 0).ok_or_else(|| anyhow!(\"Invalid HTTP request\"))?;\n    let headers = String::from_utf8_lossy(&data[..header_end]);\n\n    let first_line = headers\n        .lines()\n        .next()\n        .ok_or_else(|| anyhow!(\"Empty request\"))?;\n    let parts: Vec<&str> = first_line.split_whitespace().collect();\n\n    if parts.len() < 2 {\n        return Err(anyhow!(\"Invalid request line\"));\n    }\n\n    let method = parts[0].to_string();\n    let path = parts[1].to_string();\n    let body = data[header_end + 4..].to_vec();\n\n    Ok((method, path, body))\n}\n\nfn format_http_response(resp: &HttpResponse) -> Vec<u8> {\n    let status_text = match resp.status {\n        200 => \"OK\",\n        204 => \"No Content\",\n        404 => \"Not Found\",\n        500 => \"Internal Server Error\",\n        _ => \"Unknown\",\n    };\n","sourceCodeStart":1161,"sourceCodeEnd":1197,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/cli/sync_server.rs#L1161-L1197","documentation":"The first line of the header block must split into at least two whitespace-separated tokens, which become parts[0] (method) and parts[1] (path). Fewer than two tokens means a line like 'GET' with no path, or binary garbage that happens to contain \\r\\n\\r\\n. The parser refuses to guess, because indexing parts[1] would panic.","triggerScenarios":"parse_http_request sees a request line that splits into 0 or 1 tokens: a client writing only 'GET\\r\\n', a bare 'PING', or TLS ClientHello bytes sent to the plain HTTP port where binary leading data precedes the terminator.","commonSituations":"HTTPS requests pointed at the plain HTTP port (TLS handshake bytes as the first line); custom minimal clients omitting the path or HTTP version; scripts writing shorthand request lines; protocol-confused probes.","solutions":["Send a well-formed request line: 'METHOD /path HTTP/1.1' — at least method and path tokens.","If a TLS client is involved, point it at the TLS port or fix the scheme mismatch.","Log the offending first line to identify which client is misbehaving.","For health checks, use 'GET /health HTTP/1.1' rather than bare words."],"exampleFix":"// before (client)\nwrite!(stream, \"{}\\r\\n\\r\\n\", command)?; // single-token request line\n\n// after (client)\nwrite!(stream, \"GET {} HTTP/1.1\\r\\nHost: sync\\r\\n\\r\\n\", path)?;","handlingStrategy":"validation","validationCode":"fn request_line_well_formed(data: &[u8]) -> bool {\n    let Some(header_end) = (0..data.len().saturating_sub(3))\n        .find(|&i| &data[i..i + 4] == b\"\\r\\n\\r\\n\")\n    else { return false; };\n    String::from_utf8_lossy(&data[..header_end])\n        .lines()\n        .next()\n        .is_some_and(|line| line.split_whitespace().count() >= 2)\n}\n// before parsing:\nanyhow::ensure!(request_line_well_formed(&request_data), \"request line needs method and path\");","typeGuard":"fn request_line_well_formed(data: &[u8]) -> bool {\n    let Some(header_end) = (0..data.len().saturating_sub(3))\n        .find(|&i| &data[i..i + 4] == b\"\\r\\n\\r\\n\")\n    else { return false; };\n    String::from_utf8_lossy(&data[..header_end])\n        .lines()\n        .next()\n        .is_some_and(|line| line.split_whitespace().count() >= 2)\n}","tryCatchPattern":"match parse_http_request(&request_data) {\n    Ok((method, path, body)) => { /* dispatch */ }\n    Err(err) if err.to_string() == \"Invalid request line\" => {\n        // first line lacks method+path: reply 400 and close; log the line to find the client\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Always send 'METHOD /path HTTP/1.1' as the first line.","Check scheme and port when TLS clients are involved — TLS bytes to a plain port fail here.","Log malformed request lines server-side to identify misbehaving clients.","Use standard HTTP client libraries instead of hand-built request writers."],"tags":["http","request-parsing","sync-server","protocol"],"backgroundTag":"malformed-http-request","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}