usestrix/strix · error · ValueError

Invalid request line format

Error message

Invalid request line format

What it means

parse_raw_request() splits the raw HTTP request text and requires the first line to contain at least two whitespace-separated tokens (method and URL path). Fewer tokens raises ValueError('Invalid request line format'). It is the strict parser used when replaying/modifying captured Caido requests.

Source

Thrown at strix/tools/proxy/caido_api.py:262

        body_truncated = len(body_text) > _RESPONSE_BODY_MAX_CHARS
        if body_truncated:
            body_text = body_text[:_RESPONSE_BODY_MAX_CHARS]
        return {
            "status_code": status_code,
            "length": len(body_bytes),
            "headers": headers,
            "body": body_text,
            "body_truncated": body_truncated,
        }
    except Exception:  # noqa: BLE001 - tolerate any malformed raw bytes; None signals "unparseable" to the caller.
        return None


def parse_raw_request(raw_content: str) -> dict[str, Any]:
    lines = raw_content.split("\n")
    request_line = lines[0].strip().split(" ")
    if len(request_line) < 2:
        raise ValueError("Invalid request line format")
    method, url_path = request_line[0], request_line[1]

    parsed_headers: dict[str, str] = {}
    body_start = 0
    for i, line in enumerate(lines[1:], 1):
        if line.strip() == "":
            body_start = i + 1
            break
        if ":" in line:
            key, value = line.split(":", 1)
            parsed_headers[key.strip()] = value.strip()

    body = "\n".join(lines[body_start:]).strip() if body_start < len(lines) else ""
    return {"method": method, "url_path": url_path, "headers": parsed_headers, "body": body}


def full_url_from_components(
    original: Any,

View on GitHub (pinned to 8551339130)

Solutions

  1. Inspect the stored raw request in Caido (the request_id from the error context) and confirm line 1 looks like 'GET /path HTTP/1.1'.
  2. Skip/ignore the malformed entry and replay from a correctly captured request.
  3. Re-capture the traffic so the proxy history contains a well-formed request line.
  4. If automating, pre-check `len(raw.splitlines()[0].split()) >= 2` before calling parse functions.

Example fix

# before: raw content starts with an empty/blank line or body only
"\n\n{"a":1}"

# after: raw content starts with a valid request line
"POST /api HTTP/1.1\nHost: t.example\n\n{\"a\":1}"
Defensive patterns

Strategy: validation

Validate before calling

def has_request_line(raw: str) -> bool:
    first = raw.split("\n", 1)[0].strip()
    return len(first.split()) >= 2

raw = result.request.raw.decode("utf-8", errors="replace")
if not has_request_line(raw):
    skip(request_id)  # don't hand it to parse_raw_request

Type guard

def is_parseable_raw_request(raw: object) -> bool:
    if not isinstance(raw, (str, bytes)):
        return False
    text = raw.decode("utf-8", errors="replace") if isinstance(raw, bytes) else raw
    return len(text.split("\n")[0].strip().split(" ")) >= 2

Try / catch

try:
    components = parse_raw_request(raw_str)
except ValueError as exc:
    if "request line" in str(exc):
        log.warning("skipping malformed capture %s", request_id)
        continue
    raise

Prevention

When it happens

Trigger: repeat_request() fetches the stored request's raw bytes and hands them to parse_raw_request; if the first line is empty, a single token, or whitespace-only (mangled capture, empty raw, binary garbage decoded via errors='replace'), the parse fails.

Common situations: Captured request bodies stored without a proper request line; Caido entry containing only a body or response bytes; upstream tool wrote malformed raw content into the proxy history.

Related errors


AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15). Data as JSON: /api/errors/f3c53761eb344245. Report an issue: GitHub.