{"record":{"id":"7e2e9e0a654c0d61","repo":"spring-projects/spring-ai","slug":"could-not-read-content-length","errorCode":null,"errorMessage":"Could not read content length","messagePattern":"Could not read content length","errorType":"exception","errorClass":"AnthropicIoException","httpStatus":null,"severity":"error","filePath":"models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/http/okhttp/SpringAiAnthropicHttpClient.java","lineNumber":399,"sourceCode":"\n\tprivate static String toBaseUrl(HttpUrl url) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(url.scheme()).append(\"://\").append(url.host());\n\t\tif (url.port() != HttpUrl.defaultPort(url.scheme())) {\n\t\t\tsb.append(':').append(url.port());\n\t\t}\n\t\treturn sb.toString();\n\t}\n\n\tprivate static HttpRequestBody toHttpRequestBody(RequestBody source) {\n\t\tfinal MediaType mediaType = source.contentType();\n\t\tfinal String mediaTypeString = mediaType != null ? mediaType.toString() : null;\n\t\tfinal long length;\n\t\ttry {\n\t\t\tlength = source.contentLength();\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new AnthropicIoException(\"Could not read content length\", e);\n\t\t}\n\t\tfinal boolean isOneShot = source.isOneShot();\n\n\t\treturn new HttpRequestBody() {\n\t\t\t@Override\n\t\t\tpublic @Nullable String contentType() {\n\t\t\t\treturn mediaTypeString;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic long contentLength() {\n\t\t\t\treturn length;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean repeatable() {\n\t\t\t\treturn !isOneShot;\n\t\t\t}","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/models/spring-ai-anthropic/src/main/java/org/springframework/ai/anthropic/http/okhttp/SpringAiAnthropicHttpClient.java#L381-L417","documentation":"When converting an okio BufferedSource into an OkHttp RequestBody (toHttpRequestBody), the client calls source.contentLength(), which can throw IOException for sources whose length is not directly readable. That IOException is wrapped in AnthropicIoException 'Could not read content length'.","triggerScenarios":"Sending a request whose body is backed by a stream/source that cannot report its length (e.g. a non-replayable streaming source, a file being concurrently modified, or a source already consumed) while building the outgoing HTTP request.","commonSituations":"Uploading a file that was deleted or truncated mid-request; passing a streaming Source (e.g. from a socket or pipe) as request content; double-consuming a request body source.","solutions":["Supply request content from a replayable source: byte[] , File, or a string rather than a live stream.","If streaming is required, implement/choose a body that sets a known Content-Length or uses chunked encoding.","Verify the backing file/stream is open and readable before building the request.","Catch AnthropicIoException and inspect the cause to identify which source failed."],"exampleFix":"// before\nrequestBuilder.content(new InputStreamContent(sourceStream)); // contentLength() throws\n// after\nbyte[] bytes = sourceStream.readAllBytes();\nrequestBuilder.content(new ByteArrayContent(bytes));","handlingStrategy":"validation","validationCode":"static byte[] toBytes(InputStream in) throws IOException {\n    return in.readAllBytes(); // materialize before building the request\n}","typeGuard":"static long safeContentLength(Source src) {\n    try { return src.contentLength(); }\n    catch (IOException e) { throw new IllegalStateException(\"Source cannot report length; buffer it first\", e); }\n}","tryCatchPattern":"try {\n    return client.sendRequest(request);\n} catch (AnthropicIoException e) {\n    if (\"Could not read content length\".equals(e.getMessage())) {\n        // rebuild request with buffered byte[] content\n    }\n    throw e;\n}","preventionTips":["Prefer byte[]/File/String request content over live streams.","Never reuse an already-consumed Source for a request body.","Confirm backing files exist and are readable before building requests."],"tags":["io","okhttp","request-body"],"backgroundTag":"file-read-failed","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}