{"record":{"id":"a1f50722f1479dc8","repo":"conductor-oss/conductor","slug":"gemini-generatecontent-failed-message","errorCode":null,"errorMessage":"Gemini generateContent failed: {message}","messagePattern":"Gemini generateContent failed: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/providers/gemini/GeminiChatModel.java","lineNumber":166,"sourceCode":"                        );\n\n        String model =\n                opts != null ? opts.getModel() : (options != null ? options.getModel() : null);\n        if (model == null) {\n            model = \"gemini-2.5-flash\";\n        }\n\n        GeminiApi.GenerateContentResponse result;\n        try {\n            result =\n                    api.generateContent(\n                            model,\n                            contents,\n                            systemInstruction,\n                            toolList.isEmpty() ? null : toolList,\n                            config);\n        } catch (java.io.IOException e) {\n            throw new RuntimeException(\"Gemini generateContent failed: \" + e.getMessage(), e);\n        }\n\n        return toSpringChatResponse(result, model);\n    }\n\n    private List<GeminiApi.Tool> buildTools(GeminiChatOptions opts) {\n        List<GeminiApi.Tool> tools = new ArrayList<>();\n        if (opts == null) {\n            return tools;\n        }\n\n        // Google Search\n        if (opts.isGoogleSearchRetrieval()) {\n            tools.add(GeminiApi.Tool.withGoogleSearch());\n        }\n\n        // Code execution\n        if (opts.isCodeExecution()) {","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/providers/gemini/GeminiChatModel.java#L148-L184","documentation":"GeminiChatModel.call() wraps any java.io.IOException from GeminiApi.generateContent() into a RuntimeException. The underlying IOException (transport failure, HTTP error from the Gemini/Vertex endpoint) is preserved as the cause. This is the sole catch for all failures during a Gemini chat completion request.","triggerScenarios":"The OkHttp call to the Gemini generateContent endpoint (generativelanguage.googleapis.com for API-key mode, or a Vertex AI regional endpoint for service-account mode) fails at the transport layer: timeout, DNS failure, connection reset, or a non-2xx HTTP status returned by Google's API.","commonSituations":"Invalid or expired Gemini API key. Wrong Vertex AI project ID or location. OAuth token for Vertex AI expired or lacks permissions. Network firewall blocking Google APIs. Rate limiting (429) from Google. Model name not available in the configured region for Vertex AI.","solutions":["Inspect getCause() and its message for the specific failure.","For API-key mode: verify config.getApiKey() is valid and has the Generative Language API enabled.","For Vertex AI mode: verify config.getProjectId(), config.getLocation(), and that the GoogleCredentials have the aiplatform.endpoints.predict permission.","Verify the model name is available in your region (Vertex AI model availability varies by location).","Increase OkHttp timeouts for large-context requests."],"exampleFix":"// before — may fail silently on transient network error\nChatResponse response = geminiChatModel.call(prompt);\n\n// after — retry once on transient IOException\nChatResponse response;\ntry {\n    response = geminiChatModel.call(prompt);\n} catch (RuntimeException e) {\n    if (e.getCause() instanceof java.io.IOException && isTransient(e.getMessage())) {\n        Thread.sleep(2000);\n        response = geminiChatModel.call(prompt);\n    } else throw e;\n}","handlingStrategy":"retry","validationCode":"// Validate Gemini/Vertex config before calling chat model\nvoid validateGeminiConfig(GeminiVertexConfiguration config) {\n    boolean hasApiKey = config.getApiKey() != null && !config.getApiKey().isBlank();\n    boolean hasVertexCreds = config.getGoogleCredentials() != null\n        && config.getProjectId() != null && config.getLocation() != null;\n    if (!hasApiKey && !hasVertexCreds) {\n        throw new IllegalArgumentException(\n            \"Either apiKey or Vertex AI credentials (projectId + location + googleCredentials) required\");\n    }\n}","typeGuard":null,"tryCatchPattern":"// Retry on transient network failure\nfor (int attempt = 0; attempt < 3; attempt++) {\n    try {\n        return geminiChatModel.call(prompt);\n    } catch (RuntimeException e) {\n        if (e.getCause() instanceof java.io.IOException\n                && attempt < 2) {\n            Thread.sleep((long) Math.pow(2, attempt) * 1000);\n            continue;\n        }\n        throw new RuntimeException(\n            \"Gemini chat failed — check API key, project, location, network\", e);\n    }\n}","preventionTips":["For API-key mode: verify the key is valid and the Generative Language API is enabled in Google Cloud.","For Vertex AI mode: verify projectId, location, and that the service account has aiplatform.endpoints.predict permission.","Verify the model name is available in the configured region (Vertex AI model availability varies by location).","Set generous OkHttp timeouts for large-context Gemini requests.","Use exponential backoff retry for transient IOException causes."],"tags":["gemini","network","io","chat","vertex-ai"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}