---
name: a-patch-script-can-collapse-escapes-into-real-newlines
description: A python patch script turned Rust `\r\n` escapes into REAL newlines; the code compiled, sent LF HTTP, and the 4-byte boundary search could never match — three failure faces, one cause, none of them the server.
metadata:
  type: feedback
---

Measured 2026-09-07 (W2 gate fixes, `webserve_attachment_e2e`). I generated Rust
with a python heredoc patch script. The two-character escape `\r\n` I intended
to write into the Rust source arrived as an ACTUAL carriage-return + newline, so
the emitted code read:

    let request = format!("GET {path} HTTP/1.1
    Host: localhost
    ...

and

    raw.windows(4).position(|w| w == b"
    ")

**Rust accepts a newline inside a string literal, so this COMPILED.** The helper
then sent LF-terminated HTTP and searched for a 4-byte `\r\n\r\n` boundary using
a 2-byte literal that could never match it.

It cost three separate debugging passes because it wore three faces: an empty
body (the split missed, `unwrap_or` supplied ""), then `EOF while parsing a
value, line 1 column 0`, then finally `HTTP header boundary`. I suspected the
port, the daemon, the query handling and the fleet daemon in turn. The server
had answered correctly every single time — instrumenting the read printed
`HTTP/1.1 200 OK / content-type: application/json / content-length: 267`.

**Why:** two compounding rules. (1) An escape sequence that survives to the
target language is invisible when it does NOT — the generated file still looks
plausible, and the compiler has no objection. (2) A helper whose failure path
returns a benign empty value converts one bug into an unbounded number of
symptoms, each pointing somewhere else.

**How to apply:** write patch text that contains escapes with a RAW literal
(`r'''...'''` in python), then verify in the generated file, not in the script —
`grep -c` for a real CR in the emitted line should be 0 and the statement should
be on ONE line. And never let a parsing helper degrade quietly: the boundary
miss is now a named panic carrying the byte count, the port, the path and the
first 200 bytes, which is what turned three guesses into one measurement.
Sibling mechanism, different tool: [[grep-c-carriage-return-counts-every-line]].
See also [[never-send-a-claim-composed-before-its-check-ran]] — a patch script
that asserts before writing leaves the file untouched, so a `cargo check`
chained after it returns a GREEN for the unmodified tree; I read that stale
green twice this session.
