{"record":{"id":"6dc0a909ecd73b78","repo":"tursodatabase/turso","slug":"invalid-request-line","errorCode":null,"errorMessage":"Invalid request line","messagePattern":"Invalid request line","errorType":"console","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"cli/sync_server.rs","lineNumber":1294,"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 text_response(status: u16, body: &str) -> HttpResponse {\n    HttpResponse {\n        status,\n        content_type: \"text/plain\".to_string(),\n        body: body.as_bytes().to_vec(),\n    }\n}\n\nfn format_http_response(resp: &HttpResponse) -> Vec<u8> {","sourceCodeStart":1276,"sourceCodeEnd":1312,"githubUrl":"https://github.com/tursodatabase/turso/blob/492c4a71cd7c2649e7df83da1471b74f4b1c7aa9/cli/sync_server.rs#L1276-L1312","documentation":"Thrown by the Turso CLI sync server's hand-rolled HTTP parser (cli/sync_server.rs, parse_http_request). The first line of the request must split into at least two whitespace-separated tokens (method and path). A request line with fewer tokens - empty, whitespace-only, or a single word - is rejected as invalid instead of being executed.","triggerScenarios":"Opening a TCP connection to the sync server port and sending non-HTTP data: a TLS handshake against the plain-HTTP listener, a raw socket health check, a WebSocket upgrade, or a request line like \"GET\\r\\n\" (method only, no path).","commonSituations":"Client configured with https:// against a listener that only speaks plain HTTP, wrong port, a proxy or load balancer fronting the sync server with the wrong protocol, or a monitoring probe that sends an empty line on connect.","solutions":["Point the sync client at the exact scheme/host/port the sync server listens on (plain HTTP unless the listener is TLS-enabled)","Send a well-formed request line such as \"POST /sync HTTP/1.1\\r\\n\" - method and path are both mandatory","If you need TLS, terminate it in a proxy in front of the sync server or enable the TLS listener configuration","Reproduce with `curl -v http://host:port/` to confirm the server answers before wiring the real client"],"exampleFix":"// before (TLS client against plain-HTTP sync listener)\nclient.connect(\"https://127.0.0.1:8080\")\n// after (match the listener's protocol)\nclient.connect(\"http://127.0.0.1:8080\")","handlingStrategy":"validation","validationCode":"const url = new URL(syncUrl);\nif (url.protocol !== 'http:') {\n  throw new Error(`sync server expects plain HTTP, got ${url.protocol}`);\n}","typeGuard":null,"tryCatchPattern":"try { await syncClient.request(...); } catch (e) { if (/Invalid (request line|HTTP request)/.test(String(e.message))) throw new Error('sync endpoint is not speaking HTTP - check scheme/port'); throw e; }","preventionTips":["Build the sync URL from the same config the server was started with","Smoke-test the endpoint with curl before integrating the client","Never point TLS clients at the plain-HTTP sync listener"],"tags":["http","sync-server","request-parsing","network","cli"],"backgroundTag":"malformed-http-request","analyzedSha":"492c4a71cd7c2649e7df83da1471b74f4b1c7aa9","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}