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.

The Dominant Programmer
The Dominant Programmer
The Dominant Programmer
How to Fix Spring AI Ollama Timeout: Full Guide to Configuring OkHttp Read Timeout

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-timeout

is 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: 10MB

Key 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaConfigurationSpring BootSpring AItimeoutollamaokhttp
The Dominant Programmer
Written by

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

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.