spring-projects/spring-ai · error · OpenAIIoException

Could not read content length

Error message

Could not read content length

What it means

When converting an internal request body into an OkHttp RequestBody, SpringAiOpenAiHttpClient reads the body source's content length; an IOException while querying the length is wrapped in OpenAIIoException('Could not read content length').

Source

Thrown at models/spring-ai-openai/src/main/java/org/springframework/ai/openai/http/okhttp/SpringAiOpenAiHttpClient.java:349

	private static String toBaseUrl(HttpUrl url) {
		StringBuilder sb = new StringBuilder();
		sb.append(url.scheme()).append("://").append(url.host());
		if (url.port() != HttpUrl.defaultPort(url.scheme())) {
			sb.append(':').append(url.port());
		}
		return sb.toString();
	}

	private static HttpRequestBody toHttpRequestBody(RequestBody source) {
		final MediaType mediaType = source.contentType();
		final String mediaTypeString = mediaType != null ? mediaType.toString() : null;
		final long length;
		try {
			length = source.contentLength();
		}
		catch (IOException e) {
			throw new OpenAIIoException("Could not read content length", e);
		}
		final boolean isOneShot = source.isOneShot();

		return new HttpRequestBody() {
			@Override
			public @Nullable String contentType() {
				return mediaTypeString;
			}

			@Override
			public long contentLength() {
				return length;
			}

			@Override
			public boolean repeatable() {
				return !isOneShot;
			}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Check that the HttpRequestBody/stream you pass is open and readable at request-build time.
  2. Provide a body implementation whose content length is known (byte[] or file-backed) rather than a one-shot stream.
  3. Inspect the wrapped IOException cause to identify the failing source.

Example fix

// before
HttpRequestBody body = HttpRequestBody.fromStream(streamThatMayBeClosed);
// after
byte[] bytes = stream.readAllBytes();
HttpRequestBody body = HttpRequestBody.fromBytes(bytes);
Defensive patterns

Strategy: validation

Validate before calling

// ensure the body is materialized and readable before the call
byte[] payload = bodyStream.readAllBytes();
if (payload.length == 0) { throw new IllegalStateException("Request body is empty/closed"); }

Try / catch

try {
    return client.execute(request, options);
} catch (OpenAIIoException e) {
    if (e.getMessage().contains("content length")) {
        throw new InvalidRequestBodyException("Body stream unreadable when building request", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Sending a request with a streaming/non-repeatable body whose source throws IOException when contentLength() is queried during toHttpRequestBody, called from toHttpRequest.

Common situations: Custom HttpRequestBody implementations backed by a stream that errors on length probing (e.g. a closed or pipe-backed stream), or a body whose source is consumed before the request is built.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/5825c3b798b08680. Report an issue: GitHub.