{"record":{"id":"616d8137eeff3875","repo":"didi/DoKit","slug":"expected-expectedcontentlength-bytes-but-r-616d81","errorCode":null,"errorMessage":"expected \" + expectedContentLength + \" bytes but received \" + bytesReceived","messagePattern":"expected \" \\+ expectedContentLength \\+ \" bytes but received \" \\+ bytesReceived","errorType":"exception","errorClass":"ProtocolException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java","lineNumber":859,"sourceCode":"                    try {\n                        sink.write(source, offset, byteCount);\n                    } catch (InterruptedIOException e) {\n                        throw new SocketTimeoutException(e.getMessage());\n                    }\n                }\n\n                @Override\n                public void flush() throws IOException {\n                    if (closed) return; // Weird, but consistent with historical behavior.\n                    sink.flush();\n                }\n\n                @Override\n                public void close() throws IOException {\n                    closed = true;\n\n                    if (expectedContentLength != -1L && bytesReceived < expectedContentLength) {\n                        throw new ProtocolException(\"expected \" + expectedContentLength\n                                + \" bytes but received \" + bytesReceived);\n                    }\n\n                    sink.close();\n                }\n            };\n        }\n\n        @Override\n        public long contentLength() {\n            return expectedContentLength;\n        }\n\n        @Override\n        public final @Nullable\n        MediaType contentType() {\n            return null; // Let the caller provide this in a regular header.\n        }","sourceCodeStart":841,"sourceCodeEnd":877,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java#L841-L877","documentation":"The close() path of the fixed-length body OutputStream throws ProtocolException(\"expected N bytes but received M\") when fewer bytes than the declared expectedContentLength were written before closing. OkHttp refuses to complete a request whose body is shorter than advertised, since the server would hang waiting for the missing bytes.","triggerScenarios":"setFixedLengthStreamingMode(n) then writing fewer than n bytes (early return, exception swallowed mid-write, truncated source) and calling close().","commonSituations":"Upload interrupted by an exception that is caught and skipped; reading from a source that returns less data than its reported length (file modified concurrently); conditional writes that skip the last chunk.","solutions":["Pad or recompute: build the full body first and pass its exact size to setFixedLengthStreamingMode.","If the source can come up short, use chunked mode instead of fixed-length.","Fail fast on short reads from the source stream instead of silently closing."],"exampleFix":"// before\nconn.setFixedLengthStreamingMode(file.length());\ncopyMaybeShort(source, os);\nos.close(); // underflow -> ProtocolException\n\n// after\nconn.setChunkedStreamingMode(0); // length not guaranteed\n// or: verify copiedCount == file.length() before close, else abort","handlingStrategy":"validation","validationCode":"long declared = body.length; // or file.length()\n// after copying, before close:\nif (bytesCopied != declared) throw new IOException(\"short body: \" + bytesCopied + \"/\" + declared);\nos.close();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify copied-byte count equals the declared length before close().","Treat short reads from the source stream as errors, not as end-of-body."],"tags":["network","http","upload","content-length"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}