{"record":{"id":"2f426205d1254014","repo":"Hmbown/CodeWhale","slug":"request-exceeds-max-request-bytes-bytes","errorCode":null,"errorMessage":"request exceeds {MAX_REQUEST_BYTES} bytes","messagePattern":"request exceeds (.+?) bytes","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/control_socket.rs","lineNumber":887,"sourceCode":"    if read == 0 {\n        return Ok(None); // EOF before any content\n    }\n    if line.last() != Some(&b'\\n') {\n        // The frame exceeded the cap (or was torn mid-line). Discard the\n        // remainder so a well-behaved client finishes its write and reads\n        // the rejection; a torn frame's write lands nowhere and is ignored.\n        let mut buf = [0u8; 8192];\n        loop {\n            match stream.read(&mut buf) {\n                Ok(0) | Err(_) => break,\n                Ok(n) => {\n                    if buf[..n].contains(&b'\\n') {\n                        break;\n                    }\n                }\n            }\n        }\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\"request exceeds {MAX_REQUEST_BYTES} bytes\"),\n        ));\n    }\n    Ok(Some(String::from_utf8_lossy(&line).into_owned()))\n}\n\n#[cfg(unix)]\nfn write_response_line(stream: &mut UnixStream, value: &str) {\n    let _ = writeln!(stream, \"{value}\");\n    let _ = stream.flush();\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    // ── Verb parsing ──────────────────────────────────────────────────────","sourceCodeStart":869,"sourceCodeEnd":905,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/control_socket.rs#L869-L905","documentation":"read_request_line accumulates the control-socket request until a newline, enforcing MAX_REQUEST_BYTES. If the line grows past that cap before terminating, it returns InvalidData with 'request exceeds {MAX_REQUEST_BYTES} bytes' to bound memory from oversized or malicious input.","triggerScenarios":"A client sends a request line longer than MAX_REQUEST_BYTES without a newline — either a malformed client, a non-protocol client writing binary garbage, or a genuinely oversized command payload.","commonSituations":"Pointing a tool at the control socket that speaks a different protocol; a bug where the client never terminates the line with \\n; attempted abuse of an exposed socket.","solutions":["Shorten the request payload below MAX_REQUEST_BYTES","Ensure the client terminates each request with a newline ('\\n')","Verify the client is speaking the control socket's line-based protocol, not another format","If larger payloads are legitimately needed, raise MAX_REQUEST_BYTES in control_socket.rs and rebuild"],"exampleFix":"// before: one huge line\nsocket.write_all(payload.as_bytes())?; // payload > MAX_REQUEST_BYTES, no '\\n'\n// after\nassert!(payload.len() < MAX_REQUEST_BYTES);\nsocket.write_all(payload.as_bytes())?;\nsocket.write_all(b\"\\n\")?;","handlingStrategy":"validation","validationCode":"if payload.len() + 1 > MAX_REQUEST_BYTES {\n    return Err(\"request payload too large for control socket\".into());\n}","typeGuard":null,"tryCatchPattern":"match send_request(&mut socket, payload) {\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => {\n        eprintln!(\"request rejected: exceeds {} bytes\", MAX_REQUEST_BYTES);\n    }\n    other => other?,\n}","preventionTips":["Always terminate requests with a newline","Enforce the client-side size limit before sending","Never point non-protocol clients at the control socket","Keep command payloads small; pass large data by file reference"],"tags":["io","protocol","payload-too-large","control-socket"],"backgroundTag":"payload-too-large","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}