tursodatabase/turso · error · anyhow::Error
Invalid request line
Error message
Invalid request line
What it means
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.
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
Example fix
// before (TLS client against plain-HTTP sync listener)
client.connect("https://127.0.0.1:8080")
// after (match the listener's protocol)
client.connect("http://127.0.0.1:8080") Defensive patterns
Strategy: validation
Validate before calling
const url = new URL(syncUrl);
if (url.protocol !== 'http:') {
throw new Error(`sync server expects plain HTTP, got ${url.protocol}`);
} Try / catch
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; } Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Empty request
- Invalid HTTP request
- HTTP error! status
- HTTP request failed: . URL: , Method: , Body size: bytes
- HTTP request length overflows
AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-08-20).
Data as JSON: /api/errors/6dc0a909ecd73b78.
Report an issue: GitHub.
Appendix: source
Thrown at cli/sync_server.rs:1294
let value = line.split(':').nth(1)?.trim();
return value.parse().ok();
}
}
None
}
fn parse_http_request(data: &[u8]) -> Result<(String, String, Vec<u8>)> {
let header_end = find_header_end(data, 0).ok_or_else(|| anyhow!("Invalid HTTP request"))?;
let headers = String::from_utf8_lossy(&data[..header_end]);
let first_line = headers
.lines()
.next()
.ok_or_else(|| anyhow!("Empty request"))?;
let parts: Vec<&str> = first_line.split_whitespace().collect();
if parts.len() < 2 {
return Err(anyhow!("Invalid request line"));
}
let method = parts[0].to_string();
let path = parts[1].to_string();
let body = data[header_end + 4..].to_vec();
Ok((method, path, body))
}
fn text_response(status: u16, body: &str) -> HttpResponse {
HttpResponse {
status,
content_type: "text/plain".to_string(),
body: body.as_bytes().to_vec(),
}
}
fn format_http_response(resp: &HttpResponse) -> Vec<u8> {View on GitHub (pinned to 492c4a71cd)