sub2api/UPSTREAM_DIAGNOSTICS.md
win 12ae97b755 fix: Increase maxOutputTokens in Antigravity test request from 1 to 10
The test request was using maxOutputTokens: 1, which caused Google API to
generate only 1 token. When decoded, this single token produced "It" as the
response, making it look like an error.

Changed:
- Content: "." → "Test connection" (more meaningful prompt)
- MaxTokens: 1 → 10 (enough tokens to verify connection is working)

This fixes the issue where account test always showed "It" in the response,
which was actually just the truncated output from the single-token generation.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-11 18:49:53 +08:00

5.4 KiB
Raw Permalink Blame History

🔍 上游 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 返回:

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 返回:

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 返回:

HTTP/1.1 429 Too Many Requests

{
  "error": {
    "code": 429,
    "message": "The resource has been exhausted.",
    "errors": [...]
  }
}

场景 4: 内部服务器错误

Google API 返回:

HTTP/1.1 500 Internal Server Error

{
  "error": {
    "code": 500,
    "message": "Internal error occurred.",
    "errors": [...]
  }
}

🔧 如何看到真实的上游返回值

方法 A: 添加诊断日志 (推荐)

编辑 antigravity_gateway_service.go,在 TestConnection 函数中:

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
	}
	
	// ... 继续 ...
}

然后查看日志:

# Docker 日志
docker logs <container-id> | 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 中添加日志:

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] 输出

完成后,请将日志输出分享给我,我们就能找到真实的错误原因!