alibaba/spring-ai-alibaba · warning · RuntimeException
Retry interrupted
Error message
Retry interrupted
What it means
ToolRetryInterceptor sleeps for the computed backoff delay between attempts. If the sleeping thread is interrupted, it restores the interrupt flag and throws RuntimeException("Retry interrupted", ie), aborting the retry loop.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/toolretry/ToolRetryInterceptor.java:120
throw e;
}
// Last attempt failed: Stop the operation
if (attempt >= maxAttempts - 1) {
break;
}
// Calculate delay
long delay = calculateDelay(attempt);
log.warn("Tool '{}' failed (attempt {}/{}), retrying in {}ms: {}",
toolName, attempt + 1, maxAttempts, delay, e.getMessage());
try {
Thread.sleep(delay);
}
catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Retry interrupted", ie);
}
}
}
// All retries exhausted
if (onFailure == OnFailureBehavior.RAISE) {
throw new RuntimeException("Tool call failed after " + maxAttempts + " attempts", lastException);
}
else {
// Return error message as tool response
String errorMessage = errorFormatter != null
? errorFormatter.apply(lastException)
: "Tool call failed after " + maxAttempts + " attempts: " + lastException.getMessage();
log.error("Tool '{}' failed after {} attempts: {}", toolName, maxAttempts, lastException.getMessage());
return ToolCallResponse.of(request.getToolCallId(), request.getToolName(), errorMessage);
}
}View on GitHub (pinned to f82da0b50f)
Solutions
- Avoid interrupting the thread running the agent, or let shutdown complete the in-flight tool call
- Handle the RuntimeException and its InterruptedException cause gracefully at shutdown boundaries
- Use an executor lifecycle that waits for tasks instead of shutdownNow()
- Reduce delay/maxAttempts so retries finish before shutdown
Example fix
// before executor.shutdownNow(); // interrupts in-flight retries // after executor.shutdown(); executor.awaitTermination(30, TimeUnit.SECONDS);
Defensive patterns
Strategy: try-catch
Try / catch
try { return interceptor.interceptToolCall(request, handler); } catch (RuntimeException e) { if (e.getCause() instanceof InterruptedException) { Thread.currentThread().interrupt(); return ToolCallResponse.of("retry cancelled"); } throw e; } Prevention
- Use graceful shutdown (shutdown + awaitTermination) instead of shutdownNow
- Keep retry budgets small so calls finish before shutdown
- Preserve the interrupt flag after catching
- Run agent work on threads not subject to aggressive timeout interrupts
When it happens
Trigger: The thread executing interceptToolCall is interrupted (Thread.interrupt()) while sleeping between retries, typically during shutdown or task cancellation.
Common situations: Application shutdown or Spring context close cancelling worker threads; executor shutdownNow() on a task running an agent; timeout cancellation frameworks interrupting the tool-executing thread.
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
- Retry interrupted
- Retry interrupted
- unknown component type: + componentType.getValue()
- Multiple tools with the same name (%s)
- failed to create index
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/1def4f7fb2463208.
Report an issue: GitHub.