# 🔍 上游 API 返回值诊断指南 当你的 Antigravity 账号验证返回 "IT" 错误时,这个错误**来自上游 Google API**的响应。 ## 📊 错误链追踪 ``` 你的 curl 请求 ↓ HTTP Handler (account_handler.go:671) ↓ AccountTestService.testAntigravityAccountConnection() ├─ 调用: AntigravityGatewayService.TestConnection() │ ├─ 调用: client.LoadCodeAssist(ctx, accessToken) │ │ ↓ │ │ 🌐 Google API (真实的上游服务器) │ │ 返回: ??? (这是问题所在) │ │ │ └─ 错误处理: 什么时候会返回 "IT"? │ └─ sendErrorAndEnd(c, error_message) ↓ SSE 响应流 ↓ 你的 curl 看到: "IT" ``` ## 🎯 上游可能返回的错误 ### 场景 1: Access Token 无效 (最可能) **Google API 返回:** ```json HTTP/1.1 401 Unauthorized { "error": { "code": 401, "message": "Invalid authentication credentials", "errors": [ { "message": "Invalid authentication credentials", "domain": "global", "reason": "authenticationRequired" } ] } } ``` **在你的应用中显示为:** `"IT"`(被截断的错误信息) --- ### 场景 2: 项目配置错误 **Google API 返回:** ```json HTTP/1.1 400 Bad Request { "error": { "code": 400, "message": "The project does not have permission to call CloudAI APIs", "errors": [...] } } ``` **在你的应用中显示为:** `"IT"`(也可能是 `"Th"` 或其他前两个字符) --- ### 场景 3: 模型不可用 **Google API 返回:** ```json HTTP/1.1 429 Too Many Requests { "error": { "code": 429, "message": "The resource has been exhausted.", "errors": [...] } } ``` --- ### 场景 4: 内部服务器错误 **Google API 返回:** ```json HTTP/1.1 500 Internal Server Error { "error": { "code": 500, "message": "Internal error occurred.", "errors": [...] } } ``` --- ## 🔧 如何看到真实的上游返回值 ### 方法 A: 添加诊断日志 (推荐) 编辑 `antigravity_gateway_service.go`,在 `TestConnection` 函数中: ```go func (s *AntigravityGatewayService) TestConnection(ctx context.Context, account *Account, modelID string) (*TestConnectionResult, error) { // ... 现有代码 ... result, err := s.antigravityRetryLoop(p) if err != nil { // 添加这些行来捕获完整的上游错误信息 log.Printf("[UPSTREAM_ERROR] Type=%T", err) log.Printf("[UPSTREAM_ERROR] Message=%s", err.Error()) log.Printf("[UPSTREAM_ERROR] FullError=%#v", err) // 如果是 HTTP 错误,打印更详细的信息 if httpErr, ok := err.(interface{ StatusCode() int }); ok { log.Printf("[UPSTREAM_ERROR] StatusCode=%d", httpErr.StatusCode()) } return nil, err } // ... 继续 ... } ``` 然后查看日志: ```bash # Docker 日志 docker logs | grep "UPSTREAM_ERROR" # 或本地日志 tail -f /var/log/sub2api/server.log | grep "UPSTREAM_ERROR" ``` --- ### 方法 B: 使用网络抓包工具 启动 Charles/Fiddler,拦截 HTTPS 请求: 1. 配置你的应用使用代理 2. 运行测试请求 3. 在代理工具中观察: - **Request**: 发送给 Google API 的请求 - **Response**: Google API 返回的完整响应 --- ### 方法 C: 查看应用日志中的错误 在 `sendErrorAndEnd` 中添加日志: ```go func (s *AccountTestService) sendErrorAndEnd(c *gin.Context, msg string) error { log.Printf("[SEND_ERROR_START]") log.Printf("[SEND_ERROR_MESSAGE_LEN]=%d", len(msg)) log.Printf("[SEND_ERROR_MESSAGE]=%q", msg) // 用 %q 显示完整的字符串(含转义) log.Printf("[SEND_ERROR_BYTES]=%v", []byte(msg)) log.Printf("[SEND_ERROR_END]") s.sendEvent(c, TestEvent{ Type: "test_error", Error: msg, Success: false, }) s.sendEvent(c, TestEvent{Type: "test_complete", Success: false}) return nil } ``` --- ## 📝 真实的错误示例 ### 示例 1: Token 过期 **完整错误链:** ``` Google API 返回 401 + "Invalid authentication credentials" ↓ (在 Client 中解析) Go error: "Invalid authentication credentials" ↓ (在 TestConnection 中传播) sendErrorAndEnd() 接收: "Invalid authentication credentials" ↓ (截断?编码错误?) SSE 事件中显示: "IT" 或 "In" 或 "I" ``` ### 示例 2: Project 配置错误 **完整错误链:** ``` Google API 返回 400 + "The project does not have permission..." ↓ sendErrorAndEnd() 接收: "The project does not have permission..." ↓ 截断为前两个字符: "Th" ← 这与你看到的 "IT" 不符,说明不是这个 ``` --- ## ❓ 为什么会显示 "IT"? 最可能的解释: 1. **错误被截断** - 原文可能是 `INTERNAL_ERROR` 被截断成 `IT` 2. **错误代码** - 某些错误被转换成了短代码 `IT` 3. **部分响应** - 只有响应的一部分被返回 --- ## ✅ 下一步行动 1. **立即**: 添加上述诊断日志 2. **运行**: 执行你的测试 curl 命令 3. **检查**: 查看应用日志 4. **记录**: 复制完整的错误信息给我 --- ## 📌 检查清单 - [ ] 添加了 TestConnection 的诊断日志 - [ ] 添加了 sendErrorAndEnd 的诊断日志 - [ ] 重新编译并部署应用 - [ ] 执行了测试 curl 命令 - [ ] 检查了应用日志 - [ ] 记录了完整的 `[UPSTREAM_ERROR]` 或 `[SEND_ERROR]` 输出 --- **完成后,请将日志输出分享给我,我们就能找到真实的错误原因!**