{"record":{"id":"409712a90c8c1320","repo":"chinabugotech/hutool","slug":"failed-to-send-get-request-409712","errorCode":null,"errorMessage":"Failed to send GET request: ","messagePattern":"Failed to send GET request: ","errorType":"exception","errorClass":"AIException","httpStatus":null,"severity":"error","filePath":"hutool-ai/src/main/java/cn/hutool/ai/model/gemini/GeminiServiceImpl.java","lineNumber":476,"sourceCode":"\t * 发送Get请求\n\t * @param endpoint 请求节点\n\t * @return 请求响应\n\t */\n\t@Override\n\tprotected HttpResponse sendGet(String endpoint) {\n\t\t//链式构建请求\n\t\ttry {\n\t\t\t//设置超时3分钟\n\t\t\tfinal HttpRequest httpRequest = HttpRequest.get(config.getApiUrl() + endpoint)\n\t\t\t\t.header(Header.ACCEPT, \"application/json\")\n\t\t\t\t.header(\"x-goog-api-key\", config.getApiKey())\n\t\t\t\t.timeout(config.getTimeout());\n\t\t\tif (config.getHasProxy()) {\n\t\t\t\thttpRequest.setProxy(config.getProxy());\n\t\t\t}\n\t\t\treturn httpRequest.execute();\n\t\t} catch (final Exception e) {\n\t\t\tthrow new AIException(\"Failed to send GET request: \" + e.getMessage(), e);\n\t\t}\n\t}\n\n\t@Override\n\tprotected HttpResponse sendPost(String endpoint, String paramJson) {\n\t\t//链式构建请求\n\t\ttry {\n\t\t\tfinal HttpRequest httpRequest = HttpRequest.post(config.getApiUrl() + endpoint)\n\t\t\t\t.header(Header.CONTENT_TYPE, \"application/json\")\n\t\t\t\t.header(\"x-goog-api-key\", config.getApiKey())\n\t\t\t\t.body(paramJson)\n\t\t\t\t.timeout(config.getTimeout());\n\t\t\tif (config.getHasProxy()) {\n\t\t\t\thttpRequest.setProxy(config.getProxy());\n\t\t\t}\n\t\t\treturn httpRequest.execute();\n\t\t} catch (final Exception e) {\n\t\t\tthrow new AIException(\"Failed to send POST request：\" + e.getMessage(), e);","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-ai/src/main/java/cn/hutool/ai/model/gemini/GeminiServiceImpl.java#L458-L494","documentation":"Thrown by GeminiServiceImpl.sendGet (the Gemini-specific override of BaseAIService.sendGet) on a transport-level failure of HttpRequest.execute(). Unlike the base class, Gemini authenticates with the x-goog-api-key header instead of Bearer. Hutool-http does not throw on HTTP status codes, so 4xx/5xx are returned as HttpResponse and do NOT raise this; only connection/socket/URL/SSL/proxy failures do. Cause is preserved.","triggerScenarios":"Gemini GET (chat, getVideoOperation, file metadata) against an unreachable/wrong apiUrl, connect/read timeout, SSL handshake failure, or proxy failure. Invalid API key returns HTTP 403 (not this exception).","commonSituations":"Wrong Gemini base URL (should be https://generativelanguage.googleapis.com); regional endpoint not reachable; corporate proxy blocking googleapis.com; timeout too low for long context; transient network outage.","solutions":["Confirm config.getApiUrl() points at a reachable Gemini endpoint.","Verify network/proxy reachability to googleapis.com from the host.","Raise setTimeout/setReadTimeout for large prompts.","Inspect ex.getCause() for the real IOException.","Remember an invalid key yields HTTP 403 on the response, not this -- check status separately."],"exampleFix":"// before\nAIConfig cfg = new GeminiConfigBuilder(k).build(); // default apiUrl wrong/unreachable\nString r = gemini.chat(\"hi\"); // -> Failed to send GET request\n\n// after\nAIConfig cfg = new AIConfigBuilder(ModelName.GEMINI.getValue())\n    .setApiKey(k)\n    .setApiUrl(\"https://generativelanguage.googleapis.com\")\n    .setTimeout(60_000)\n    .build();","handlingStrategy":"try-catch","validationCode":"// Validate Gemini endpoint reachability before the call\nString base = config.getApiUrl();\nif (StrUtil.isBlank(base) || !base.contains(\"googleapis.com\")) {\n    throw new IllegalStateException(\"suspect Gemini apiUrl: \" + base);\n}\nif (config.getTimeout() < 30_000) config.setTimeout(60_000);","typeGuard":null,"tryCatchPattern":"try {\n    return gemini.chat(prompt);\n} catch (AIException e) {\n    if (e.getMessage().startsWith(\"Failed to send GET request\")) {\n        Throwable root = e.getCause(); // UnknownHostException / SocketTimeoutException\n        // transport only; an invalid key returns HTTP 403 on the response, not this\n    }\n    throw e;\n}","preventionTips":["Set the Gemini base URL explicitly.","Allow egress to googleapis.com (proxy/firewall).","Distinguish transport errors from HTTP 403 key errors."],"tags":["network","http","transport","gemini","timeout"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}