{"record":{"id":"b1d0271c2bfd847b","repo":"alibaba/spring-ai-alibaba","slug":"primary-model-failed","errorCode":null,"errorMessage":"Primary model failed: {}","messagePattern":"Primary model failed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/modelfallback/ModelFallbackInterceptor.java","lineNumber":77,"sourceCode":"\t@Override\n\tpublic ModelResponse interceptModel(ModelRequest request, ModelCallHandler handler) {\n\t\tException lastException = null;\n\n\t\t// Try primary model first\n\t\ttry {\n\t\t\tModelResponse modelResponse = handler.call(request);\n\t\t\tMessage message = (Message) modelResponse.getMessage();\n\t\t\t\n\t\t\t// Check if response contains error indicator\n\t\t\tif (message.getText() != null && message.getText().contains(\"Exception:\")) {\n\t\t\t\tthrow new RuntimeException(message.getText());\n\t\t\t}\n\t\t\t\n\t\t\t// Return successful response\n\t\t\treturn modelResponse;\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlog.warn(\"Primary model failed: {}\", e.getMessage());\n\t\t\tlastException = e;\n\t\t}\n\n\t\t// Try fallback models in sequence\n\t\tfor (int i = 0; i < fallbackModels.size(); i++) {\n\t\t\tChatModel fallbackModel = fallbackModels.get(i);\n\t\t\ttry {\n\t\t\t\tlog.info(\"Trying fallback model {} of {}\", i + 1, fallbackModels.size());\n\n\t\t\t\t// Call the fallback model directly\n\t\t\t\tPrompt prompt = new Prompt(request.getMessages(), request.getOptions());\n\t\t\t\tvar response = fallbackModel.call(prompt);\n\n\t\t\t\treturn ModelResponse.of(response.getResult().getOutput());\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tlog.warn(\"Fallback model {} failed: {}\", i + 1, e.getMessage());\n\t\t\t\tlastException = e;","sourceCodeStart":59,"sourceCodeEnd":95,"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/modelfallback/ModelFallbackInterceptor.java#L59-L95","documentation":"ModelFallbackInterceptor.interceptModel catches any Exception thrown by the primary ChatModel call, logs 'Primary model failed' with the message, records it as lastException, and proceeds to iterate the configured fallbackModels in order. This is informational in the normal path; it only precedes a hard failure if every fallback also fails.","triggerScenarios":"The primary model.call(prompt) throws — network/timeout errors, 401/403 auth failures, rate limits, model unavailability, or invalid options — during a ChatModel invocation routed through ModelFallbackInterceptor.","commonSituations":"Expired or missing DashScope/OpenAI API key; regional endpoint outage; request exceeding context limit; transient 429 rate limiting during bursts; misconfigured model name after a version upgrade.","solutions":["Read the logged e.getMessage() to identify the underlying cause (auth vs network vs limit)","Configure at least one healthy fallbackModel in the interceptor builder with compatible capabilities","Fix the primary model's credentials/endpoint; a fallback chain should be a safety net, not the norm","Add retry (ModelRetryInterceptor) in front of fallback for transient errors","Monitor the warnings — frequent occurrences indicate the primary model config is broken"],"exampleFix":"// before\nModelFallbackInterceptor.of(primaryModel); // no fallbacks configured\n// after\nModelFallbackInterceptor interceptor = ModelFallbackInterceptor.builder()\n    .primaryModel(primaryModel)\n    .fallbackModels(List.of(backupDashScopeModel, backupOpenAiModel))\n    .build();","handlingStrategy":"fallback","validationCode":"Objects.requireNonNull(primaryModel, \"primary model required\");\nif (fallbackModels.isEmpty()) throw new IllegalStateException(\"ModelFallbackInterceptor needs at least one fallback model\");","typeGuard":"boolean chainIsHealthy(List<ChatModel> models) { return models != null && !models.isEmpty() && models.stream().allMatch(Objects::nonNull); }","tryCatchPattern":"try { return interceptor.interceptModel(request, chain); }\ncatch (RuntimeException e) { log.error(\"All models failed\", e); return degrade(request); }","preventionTips":["Keep API keys valid and rotate before expiry; validate at startup with a cheap health call","Mix providers across the fallback chain to avoid correlated outages","Alert on repeated 'Primary model failed' warnings","Use ModelRetryInterceptor for transient errors before burning fallbacks"],"tags":["model","fallback","resilience","interceptor"],"backgroundTag":"upstream-api-error","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"}