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();
}
@OverrideView on GitHub (pinned to 98a7beda4f)
Solutions
- Inspect the attached throwable in the log to see the root cause (HTTP status or exception class).
- For 429s, reduce request rate or configure larger backoff via spring.retry properties / RetryCustomizer.
- For 401/403, fix the API key — retries will not help.
- 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
- Tune spring.retry max-attempts and backoff intervals for your provider's rate limits
- Distinguish non-retryable errors (401/403) from transient ones (429/5xx) before retrying
- Monitor WARN logs for retry-count trends as an early signal of upstream degradation
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
- HTTP %s - %s
- Retry error. Retry count:
- Tool call limit exceeded (dynamic message: tool name and lim
- Functional bean with name %s does not exist in the context.
- Impossible to resolve the type of bean
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/b8012407e2722e4e.
Report an issue: GitHub.