The error message was right
- #debugging
Placeholder post — replace with your own writing.
The service returned a binary file instead of a web page. Not an error page, not a 500 — an actual download prompt, on a URL that had served HTML for two years.
My first instinct was that the error was lying. It usually isn’t.
What I checked, in the wrong order
I restarted the process. I checked the deployed artifact. I diffed the config against the previous release. I read the application logs closely enough to notice they contained nothing unusual, which should have told me the application was never involved.
Three hours in, I finally looked at the layer below.
The actual cause
A listener directive was misconfigured, and the server was speaking one protocol on a port where clients expected another. The browser did exactly what you’d expect when handed bytes it can’t parse as a document: it offered to save them.
The lesson I keep re-learning
When the failure is weird rather than wrong — a download instead of a page, a hang instead of an error — the problem is usually not in the code you were last editing. It’s in the layer you’ve stopped thinking of as a moving part.