{"record":{"id":"365cfecb361e4dc3","repo":"conductor-oss/conductor","slug":"gemini-embedcontent-failed","errorCode":null,"errorMessage":"Gemini embedContent failed","messagePattern":"Gemini embedContent failed","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/providers/gemini/GeminiVertex.java","lineNumber":94,"sourceCode":"        return List.of(ALIAS);\n    }\n\n    @Override\n    public List<Float> generateEmbeddings(EmbeddingGenRequest embeddingGenRequest) {\n        try {\n            GeminiApi.EmbedContentResponse resp =\n                    geminiApi.embedContent(\n                            embeddingGenRequest.getModel(),\n                            embeddingGenRequest.getText(),\n                            embeddingGenRequest.getDimensions());\n            if (resp.embedding() == null || resp.embedding().values() == null) {\n                throw new RuntimeException(\"No embeddings returned from Gemini API\");\n            }\n            return resp.embedding().values();\n        } catch (RuntimeException e) {\n            throw e;\n        } catch (Exception e) {\n            throw new RuntimeException(\"Gemini embedContent failed\", e);\n        }\n    }\n\n    @Override\n    public ChatModel getChatModel() {\n        return new GeminiChatModel(geminiApi);\n    }\n\n    @Override\n    public ChatOptions getChatOptions(ChatCompletion input) {\n        return GeminiChatOptions.builder()\n                .model(input.getModel())\n                .temperature(input.getTemperature())\n                .maxTokens(input.getMaxTokens())\n                .frequencyPenalty(input.getFrequencyPenalty())\n                .presencePenalty(input.getPresencePenalty())\n                .stopSequences(input.getStopWords())\n                .topK(input.getTopK())","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/providers/gemini/GeminiVertex.java#L76-L112","documentation":"GeminiVertex.generateEmbeddings() catches any checked Exception (not RuntimeException) from the embedContent API call and wraps it with this generic message. The catch ordering is deliberate: RuntimeException (including error 190's message) is rethrown as-is at the first catch, then all other exceptions (IOException, etc.) are wrapped here. The original exception is preserved as the cause.","triggerScenarios":"An IOException or other checked exception during the HTTP call to the Gemini embedContent endpoint: connection timeout, DNS failure, HTTP 4xx/5xx from Google's embeddings API, or a JSON deserialization error on the response.","commonSituations":"Network connectivity issues to Google's API. Invalid or expired API key causing a 401/403. Vertex AI project/location misconfiguration. Rate limiting from the embeddings endpoint. Response body malformed (not valid JSON for EmbedContentResponse).","solutions":["Inspect getCause() for the specific checked exception — it is always preserved.","For IOException causes: verify network connectivity and API endpoint reachability.","Verify the API key / Vertex AI credentials are valid for embeddings.","Check if the response body was malformed — this may indicate an API version mismatch between the client and Google's endpoint."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Validate connectivity and credentials before calling\nvoid validateGeminiEmbeddingConfig(String apiKey, String model) {\n    if (apiKey == null || apiKey.isBlank()) {\n        throw new IllegalArgumentException(\"Gemini API key required for embeddings\");\n    }\n    if (model == null || model.isBlank()) {\n        throw new IllegalArgumentException(\"Embedding model name required\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return vertex.generateEmbeddings(request);\n} catch (RuntimeException e) {\n    // Error 190's RuntimeException is rethrown as-is by GeminiVertex;\n    // this catches only the wrapped checked-exception path\n    if (e.getMessage().equals(\"Gemini embedContent failed\")\n            && e.getCause() instanceof java.io.IOException\n            && isTransient(e.getCause())) {\n        Thread.sleep(2000);\n        return vertex.generateEmbeddings(request);\n    }\n    throw new RuntimeException(\"Gemini embeddings transport failure\", e);\n}","preventionTips":["Verify network connectivity to the Gemini embeddings endpoint.","Ensure the API key or Vertex AI credentials are valid and non-expired.","Distinguish this (wrapped checked exception) from error 190 (RuntimeException rethrown as-is) by message.","Use retry with backoff for transient IOException causes."],"tags":["gemini","embeddings","network","io","error-wrapping"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}