spring-projects/spring-ai · warning

Retry error. Retry count:

Error message

Retry error. Retry count:

What it means

SpringAiRetryAutoConfiguration registers a RetryListener whose onRetryFailure logs 'Retry error. Retry count:<n>' at WARN with the throwable. This is a log message, not a thrown error: it signals that a retryable operation (typically model API calls via RetryTemplate) failed and the backoff/retry policy is being applied.

Source

Thrown at auto-configurations/common/spring-ai-autoconfigure-retry/src/main/java/org/springframework/ai/retry/autoconfigure/SpringAiRetryAutoConfiguration.java:82

	public RetryTemplate retryTemplate(SpringAiRetryProperties properties) {
		RetryPolicy retryPolicy = RetryPolicy.builder()
			.maxRetries(properties.getMaxAttempts())
			.includes(TransientAiException.class)
			.includes(ResourceAccessException.class)
			.delay(properties.getBackoff().getInitialInterval())
			.multiplier(properties.getBackoff().getMultiplier())
			.maxDelay(properties.getBackoff().getMaxInterval())
			.build();

		RetryTemplate retryTemplate = new RetryTemplate(retryPolicy);
		retryTemplate.setRetryListener(new RetryListener() {
			private final AtomicInteger retryCount = new AtomicInteger(0);

			@Override
			public void onRetryFailure(RetryPolicy policy, Retryable<?> retryable, Throwable throwable) {
				int currentRetries = this.retryCount.incrementAndGet();
				if (logger.isWarnEnabled()) {
					logger.warn("Retry error. Retry count:" + currentRetries, throwable);
				}
			}
		});
		return retryTemplate;
	}

	@Bean
	@ConditionalOnMissingBean
	public ResponseErrorHandler responseErrorHandler(SpringAiRetryProperties properties) {

		return new ResponseErrorHandler() {

			@Override
			public boolean hasError(ClientHttpResponse response) throws IOException {
				return response.getStatusCode().isError();
			}

			@Override

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Inspect the attached throwable in the log to see the root cause (HTTP status or exception class).
  2. For 429s, reduce request rate or configure larger backoff via spring.retry properties / RetryCustomizer.
  3. For 401/403, fix the API key — retries will not help.
  4. If retries exhaust, the final exception surfaces from the client call; handle it at the call site.

Example fix

// application.properties: tune transient retry behavior
// before (defaults)
// after
spring.retry.max-attempts=10
spring.retry.backoff.initial-interval=2000
spring.retry.backoff.multiplier=2
Defensive patterns

Strategy: retry

Try / catch

try { model.call(prompt); } catch (NonTransientAiException | RestClientException e) { /* after retries exhausted; check root cause logged by the RetryListener */ }

Prevention

When it happens

Trigger: Any operation executed through the auto-configured RetryTemplate (e.g. OpenAI/other model client calls) that throws a retryable exception — transient 429/5xx responses, connection resets, timeouts — on each failed attempt including the final one.

Common situations: Rate limiting by the model provider; expired/invalid API key producing 401 (retried then exhausted); network flakiness in CI; overloaded upstream service.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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