{"record":{"id":"388364d563684749","repo":"alibaba/spring-ai-alibaba","slug":"model-call-failed-maximum-number-of-retries-reach-388364","errorCode":null,"errorMessage":"Model call failed, maximum number of retries reached.","messagePattern":"Model call failed, maximum number of retries reached\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/modelretry/ModelRetryInterceptor.java","lineNumber":134,"sourceCode":"\t\t\t\t\t}\n\n\t\t\t\t\t// For non-retryable exceptions, return immediately.\n\t\t\t\t\treturn modelResponse;\n\t\t\t\t}\n\n\t\t\t\t// Successful response\n\t\t\t\tif (attempt > 1) {\n\t\t\t\t\tlog.info(\"The model call succeeded after the {}th attempt.\", attempt);\n\t\t\t\t}\n\t\t\t\treturn modelResponse;\n\n\t\t\t} catch (Exception e) {\n\t\t\t\tlastException = e;\n\t\t\t\tlog.warn(\"Model call failed (attempted {}/{}): {}\", attempt, maxAttempts, e.getMessage());\n\n\t\t\t\tif (attempt >= maxAttempts) {\n\t\t\t\t\tlog.error(\"The maximum number of retries has been reached {}, and the model call has failed.\", maxAttempts);\n\t\t\t\t\tthrow new RuntimeException(\"Model call failed, maximum number of retries reached.\", lastException);\n\t\t\t\t}\n\n\t\t\t\t// Determine if an exception can be retried.\n\t\t\t\tif (!retryableExceptionPredicate.test(e)) {\n\t\t\t\t\tlog.warn(\"Exceptions cannot be retried and are thrown immediately: {}\", e.getMessage());\n\t\t\t\t\tthrow new RuntimeException(\"Model call failed (non-retryable exception)\", e);\n\t\t\t\t}\n\n\t\t\t\t// Wait and try again\n\t\t\t\tif (currentDelay > 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlog.info(\"Retry after {} ms\", currentDelay);\n\t\t\t\t\t\tThread.sleep(currentDelay);\n\t\t\t\t\t} catch (InterruptedException ie) {\n\t\t\t\t\t\tThread.currentThread().interrupt();\n\t\t\t\t\t\tthrow new RuntimeException(\"Retry interrupted\", ie);\n\t\t\t\t\t}\n\t\t\t\t}","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/modelretry/ModelRetryInterceptor.java#L116-L152","documentation":"ModelRetryInterceptor's generic catch block: a direct exception from handler.call(request) occurred on the final allowed attempt (attempt >= maxAttempts), so it throws RuntimeException(\"Model call failed, maximum number of retries reached.\") with the last exception preserved as the cause. The retry policy gave up after exhausting all attempts.","triggerScenarios":"interceptModel where handler.call throws on every one of maxAttempts attempts (e.g. persistent HTTP 4xx/5xx, timeout, I/O error); on the final attempt the `attempt >= maxAttempts` check fires before the retryability predicate is consulted.","commonSituations":"Provider outage or sustained rate limiting outlasting the retry window; wrong API key causing every call to fail; model name not found on the target endpoint; local network/firewall blocking the provider consistently.","solutions":["Inspect getCause() of this RuntimeException — it holds the final underlying model-call exception; fix that root problem.","Check provider status page and your API key validity/quota; 401/429 errors will fail every attempt.","Raise maxAttempts or lengthen backoff if failures are transient bursts (rate limit spikes).","Combine with ModelFallbackInterceptor so a different model is tried after retries are exhausted."],"exampleFix":"// before: retries then hard failure\nModelRetryInterceptor.builder().maxAttempts(3).build();\n// after: retry then fall back to another provider\nvar retry = ModelRetryInterceptor.builder().maxAttempts(3).build();\nvar fallback = ModelFallbackInterceptor.builder().addFallbackModel(otherProviderModel).build();","handlingStrategy":"try-catch","validationCode":"// Validate configuration before calling the model\nif (apiKey == null || apiKey.isBlank()) throw new IllegalStateException(\"Missing provider API key\");\nif (modelName == null || !allowedModels.contains(modelName)) throw new IllegalStateException(\"Unknown model: \" + modelName);","typeGuard":null,"tryCatchPattern":"try {\n    return retryInterceptor.interceptModel(request, handler);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Model call failed, maximum number of retries reached.\")) {\n        Throwable root = e.getCause();\n        log.error(\"All {} attempts failed; final cause: {}\", maxAttempts, root, root);\n        throw new ModelCallException(root); // typed wrapper for callers\n    }\n    throw e;\n}","preventionTips":["Verify API keys, model names, and quotas before deploying; 401/404 fail every attempt.","Subscribe to provider status feeds and set up health probes.","Combine retry with cross-provider fallback for resilience."],"tags":["retry-exhausted","llm","network","api"],"backgroundTag":"retry-limit-exceeded","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}