How to Fix Spring AI Ollama Timeout: Full Guide to Configuring OkHttp Read Timeout
The article explains why Spring AI Ollama requests time out after 10 seconds despite server‑side timeout settings, analyzes the independent OkHttp read timeout and other ineffective configurations, and provides a step‑by‑step solution that creates a custom OllamaApi bean with a longer OkHttp read timeout to permanently fix the issue.
Problem Description
When using spring-ai-ollama-spring-boot-starter 1.0.0-M6 in a Spring Boot 3.2.5 project to call a local Ollama model ( qwen2.5:7b-instruct), the chat API throws a ResourceAccessException after about 10 seconds, even though spring.ai.ollama.chat.options.timeout: 120s is set in application.yml.
Root Cause
Two independent timeout mechanisms
Model‑side timeout ( chat.options.timeout ) is sent in the POST /api/chat request body and tells the Ollama server how long it may generate. It does not affect the Java client’s wait time.
HTTP client read timeout (OkHttp) is the maximum time the Java process will wait for a response. OkHttp’s default readTimeout = 10_000ms (10 seconds), which explains the observed failure.
Only when the HTTP read timeout exceeds the model generation time can the request complete successfully.
Why common configurations fail
spring.restclient.read-timeoutis ineffective because Spring AI Ollama creates its own RestClient instance, bypassing the global RestClientCustomizer. SimpleClientHttpRequestFactory is ineffective because the underlying client is an OkHttpClient, not the JDK HttpURLConnection that the factory would configure. spring.okhttp.read-timeout is ineffective (or causes startup errors) because the property prefix for OkHttp is spring.okhttp, and even with the correct prefix the auto‑configuration does not use the Spring‑managed OkHttpClient bean.
A duplicate top‑level spring: key in YAML also triggers a DuplicateKeyException.
Common pitfalls when defining a custom Bean
The constructor signature of OllamaApi in version 1.0.0-M6 is
OllamaApi(String baseUrl, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder). Using a two‑argument constructor causes compilation errors.
Solution
Custom OllamaApi Bean with explicit OkHttp timeout
Create a configuration class that builds an OkHttpClient with a read timeout longer than the model timeout, wraps it in an OkHttp3ClientHttpRequestFactory, builds a RestClient.Builder with that factory, provides a default WebClient.Builder, and injects them into the three‑argument OllamaApi constructor.
Steps:
Create OllamaTimeoutConfig.java in the project.
Inject spring.ai.ollama.base-url via @Value.
Build an OkHttpClient with connectTimeout(Duration.ofSeconds(30)), readTimeout(Duration.ofMinutes(3)), writeTimeout(Duration.ofSeconds(60)).
Create an OkHttp3ClientHttpRequestFactory with the custom client and use it in a RestClient.Builder.
Provide an empty WebClient.Builder instance.
Return a new OllamaApi using the three‑argument constructor.
Full code:
package com.badao.ai.config;
import okhttp3.OkHttpClient;
import org.springframework.ai.ollama.api.OllamaApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
import java.time.Duration;
@Configuration
public class OllamaTimeoutConfig {
@Value("${spring.ai.ollama.base-url}")
private String baseUrl;
@Bean
public OllamaApi ollamaApi() {
// 1. custom OkHttpClient timeout
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(Duration.ofSeconds(30))
.readTimeout(Duration.ofMinutes(3)) // > model timeout
.writeTimeout(Duration.ofSeconds(60))
.build();
// 2. OkHttp3ClientHttpRequestFactory (deprecated but works)
OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
// 3. RestClient.Builder with custom factory
RestClient.Builder restClientBuilder = RestClient.builder()
.baseUrl(baseUrl)
.requestFactory(factory);
// 4. Provide WebClient.Builder (empty)
WebClient.Builder webClientBuilder = WebClient.builder();
// 5. Use the correct three‑arg constructor
return new OllamaApi(baseUrl, restClientBuilder, webClientBuilder);
}
}Since the HTTP client timeout is now under full control, the unrelated spring.restclient and spring.okhttp entries can be removed from application.yml for clarity.
server:
port: 885
logging:
level:
com.badao: debug
org.springframework.ai: debug
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: qwen2.5:7b-instruct
temperature: 0.5
timeout: 120s # keep server‑side timeout
embedding:
options:
model: nomic-embed-text
timeout: 120s
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MBKey Takeaways
Read timeout must be larger than the model timeout (e.g., 3 minutes vs. 2 minutes).
The deprecated OkHttp3ClientHttpRequestFactory works; switching to another HTTP client adds unnecessary complexity.
Avoid adding extra OkHttp settings in YAML that could interfere with the custom bean.
Verification
Rebuild and start the application.
Send the previously timing‑out RAG request.
Confirm the logs no longer show “Read timed out” or SocketTimeoutException.
Observe that the model returns results even when processing exceeds 10 seconds or a full minute.
Conclusion
The root of the issue is the default 10‑second read timeout of OkHttp used by Spring AI Ollama, which is independent of the server‑side chat.options.timeout. By defining a custom OllamaApi bean that supplies an OkHttpClient with a sufficiently long read timeout and injecting it via the proper constructor, the timeout problem is permanently resolved.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
The Dominant Programmer
Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
