handler wrote more than declared Content-Length
I am getting periodic errors like
{"level":"error","ts":1732885448.9047446,"msg":"write error","error":"http2: handler wrote more than declared Content-Length"}
in my logs. Tried to debug what's happening, and do not see anything obvious. Attaching debug log (zipped since it's quite big) caddy_bck.zip. It has 2 instances of this error. My best guess would be that it's actually a false-positive, since in both cases there is a failed to copy the response body: http2: stream closed message right after, although not sure if that would even make sense. Definitely not related to specific pages (or types of those), at least not able to replicate this on test, just happens on PROD.
My understanding is that it's not normal, possibly a bug somewhere, but unsure how to catch it exactly. I know there was #38, and I am also using Brotli, Zstd, so maybe something wrong with any of those in similar manner? I am launching FrankenPHP in Docker with this config.Caddy config is here (note it's JSON5, not JSON).
Thanks for the report. Wow a 18k line config! I'll look at this soon. I appreciate the full details like the logs and config, but due to their size it may take some time. If you can figure out a minimally reproducible case that would make a fix arrive quite speedily.
The config may look big, but most of the size is from MIME mappings (would not mind to have an alternative way). There are comments there, so you should be able to strip away unnecessary stuff. Log is a debug one + access log, I enabled it this way specifically to capture the errors an everything around them, so you probably need to focus on what's around "more than declared" messages. Unfortunately, I do not know conditions under which this happens. I just found them in my production log, tried to see if I can link them to something based on what I can get in debug log, but... I do not see anything obvious, besides the stream being closed after those messages, but that may be unrelated. Perhaps logging can be improved, so that we can link these kinds of errors to specific requests? Like... Request ID in logs or something similar?
I would start fiddling with "encode" handlers (see if removing them resolves the error, etc) -- and also verify that the proxied backends (PHP pages?) aren't sending more than they declare too.
question is - what pages? I tested those that around the errors - no issues. Of course they may be edge-cases, and I need some special conditions to trigger the errors, but I would still need to know where to put some extra logging. Generally, they seem to not be sending more than declared, though.
This error isn't too hard to trigger - I've just seen it in a debugging session where PHP returned an exception and a backtrace instead of the expected page.
Unfortunately, that means you only get status 500 and an otherwise empty page - not too useful for debugging :-(
It would be really useful to have a way to display and/or log what was actually returned from PHP (so that I can see the exception etc.). This could be an option "IgnoreContentLength" to pass through the content even if it doesn't match the declared size, and/or an option "LogContentOnLenghMismatch" which would "only" log the whole content.
Well, for me the I do not display error messages in PHP, they go to log (through custom function which does log the page, that triggered the error). I also send Content-Length header from PHP only when I do get HTML generated (via Twig) as, practically, last step, which will happen only if there was something to generate, including custom error pages in case of failure. The way things are written I am aware of only one condition, when nothing will be sent: when Twig fails completely on 2 tries, meaning there is a misconfig in the Twig Environment (not template error), and I catch this kind of stuff on dev right away.
I think it's more likely that this is false positive, and the request is actually cancelled by client, so the connection gets closed before the full body is transferred, since failed to copy the response body, but then the body size probably would be less? Unless Processing is not stopped right away and Caddy updates Content-Length on its own.
My point is, I do not think this is related to PHP script failing and displaying an error.