{"record":{"id":"45e174f5e2d25d71","repo":"alibaba/spring-ai-alibaba","slug":"message-gettext","errorCode":null,"errorMessage":"${message.getText()}","messagePattern":"\\$\\{message\\.getText\\(\\)\\}","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/modelfallback/ModelFallbackInterceptor.java","lineNumber":70,"sourceCode":"\t\tthis.fallbackModels = new ArrayList<>(builder.fallbackModels);\n\t}\n\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\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());","sourceCodeStart":52,"sourceCodeEnd":88,"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#L52-L88","documentation":"ModelFallbackInterceptor wraps the model call; if the returned message text contains the substring 'Exception:' it treats the response as an error-indicator payload and rethrows it as a RuntimeException with the full message text. This catches models/adapters that surface failures as textual output rather than thrown exceptions.","triggerScenarios":"The underlying model (or a fallback/mock adapter) returns a Message whose text contains 'Exception:', e.g. 'RuntimeException: quota exceeded' rendered as the completion; interceptModel then throws RuntimeException(message.getText()).","commonSituations":"Mock or test models that return error strings as legitimate text; a model echoing an exception from a tool result that happens to contain 'Exception:'; provider-side failure text passed through as a normal completion.","solutions":["Inspect the full message text in the thrown RuntimeException to identify the underlying cause and fix it (quota, auth, invalid request).","If this is a false positive (legitimate content containing 'Exception:'), rephrase content or adjust the interceptor's detection logic.","Ensure your fallback model/adapter throws proper exceptions instead of returning error text as completions."],"exampleFix":"// before (model returns error text)\n// RuntimeException: java.util.concurrent.TimeoutException while calling tool\n// after: handle it explicitly\ncatch (RuntimeException e) {\n    logger.warn(\"Model fallback reported: {}\", e.getMessage());\n    return fallbackResponse;\n}","handlingStrategy":"try-catch","validationCode":"Message msg = modelResponse.getMessage();\nString text = msg == null ? null : msg.getText();\nboolean looksLikeError = text != null && text.contains(\"Exception:\");\nif (looksLikeError) { handleFallbackFailure(text); }","typeGuard":"boolean isCleanResponse(Message m) { return m != null && m.getText() != null && !m.getText().contains(\"Exception:\"); }","tryCatchPattern":"try { return interceptor.interceptModel(request, handler); } catch (RuntimeException e) {\n    log.error(\"Model/fallback error text: {}\", e.getMessage());\n    return errorResponse(request);\n}","preventionTips":["Make fallback adapters throw real exceptions instead of returning error text.","Avoid returning user/tool content that literally contains 'Exception:' from the model.","Log and inspect the full message text to diagnose the underlying provider failure."],"tags":["java","agent","model-fallback"],"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"}