{"record":{"id":"1044484370af72db","repo":"flipped-aurora/gin-vue-admin","slug":"w-104448","errorCode":null,"errorMessage":"调用上游大模型流式服务失败: %w","messagePattern":"调用上游大模型流式服务失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/auto_code_llm.go","lineNumber":86,"sourceCode":"\tif responseMode == \"\" {\n\t\tpayload[\"response_mode\"] = \"streaming\"\n\t}\n\n\tres, err := request.HttpRequestWithContextAndTimeout(\n\t\tctx,\n\t\tpath,\n\t\thttp.MethodPost,\n\t\tmap[string]string{\n\t\t\t\"Accept\":          \"text/event-stream\",\n\t\t\t\"Accept-Encoding\": \"identity\", // 禁止 gzip，避免 SSE 流被压缩导致缓冲卡住\n\t\t\t\"Cache-Control\":   \"no-cache\",\n\t\t},\n\t\tnil,\n\t\tpayload,\n\t\t-1, // 不设置 client.Timeout，SSE 流的生命周期由 ctx 控制\n\t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"调用上游大模型流式服务失败: %w\", err)\n\t}\n\treturn res, nil\n}\n\nfunc buildLLMAutoPath(llm common.JSONMap) (string, error) {\n\tif global.GVA_CONFIG.AutoCode.AiPath == \"\" {\n\t\treturn \"\", errors.New(\"请先前往插件市场个人中心获取 AiPath 并填写到 config.yaml 中\")\n\t}\n\n\tmode := strings.TrimSpace(fmt.Sprintf(\"%v\", llm[\"mode\"]))\n\tif mode == \"\" {\n\t\treturn \"\", errors.New(\"llmAuto 缺少 mode 参数\")\n\t}\n\n\treturn strings.ReplaceAll(global.GVA_CONFIG.AutoCode.AiPath, \"{FUNC}\", mode), nil\n}\n\nfunc cloneLLMAutoJSONMap(src common.JSONMap) common.JSONMap {","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/auto_code_llm.go#L68-L104","documentation":"This error is wrapped and returned by LLMAutoStream in server/service/system/auto_code_llm.go when the HTTP request to the upstream LLM streaming (SSE) service fails. It wraps the underlying transport error with %w, so the root cause (DNS failure, TLS handshake, connection refused/reset, context cancellation/deadline) is preserved in the chain. Note client.Timeout is intentionally unset (-1); the stream lifecycle is governed by the passed ctx, so context deadlines and cancellations surface here.","triggerScenarios":"Calling LLMAutoStream when the upstream LLM endpoint (base URL / AiPath from global.GVA_CONFIG.AutoCode) is unreachable or misconfigured, DNS resolution fails, TLS handshake fails, the connection is refused or reset during the request, or the ctx passed to LLMAutoStream is cancelled or exceeds its deadline before the HTTP call completes.","commonSituations":"Dev/staging environments without egress access to the LLM provider; wrong AutoCode base URL/AiPath after migrating environments; corporate proxy or firewall blocking the request; upstream LLM provider outage or endpoint change; callers passing a too-short ctx timeout; API provider switched without updating config.","solutions":["Unwrap the returned error (errors.Unwrap / %v) to identify the exact transport cause (connection refused, DNS, TLS, context deadline).","Verify global.GVA_CONFIG.AutoCode base URL/AiPath points to the correct upstream LLM streaming endpoint and curl it from the server host.","Check server egress: proxy env vars (HTTP_PROXY/HTTPS_PROXY), firewall rules, DNS resolution for the upstream host.","If the cause is context deadline exceeded, extend the ctx timeout passed into LLMAutoStream or investigate the early cancellation.","If the provider endpoint changed or is down, update the endpoint config or retry with backoff."],"exampleFix":"// before\nres, err := svc.LLMAutoStream(ctx, payload)\nif err != nil {\n    return err // opaque failure\n}\n\n// after\nres, err := svc.LLMAutoStream(ctx, payload)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        return fmt.Errorf(\"LLM stream timed out, retry or extend deadline: %w\", err)\n    }\n    return fmt.Errorf(\"LLM auto stream failed: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"import (\n    \"net/http\"\n    \"time\"\n)\n\nfunc upstreamReachable(baseURL string) error {\n    client := &http.Client{Timeout: 5 * time.Second}\n    resp, err := client.Get(baseURL)\n    if err != nil {\n        return fmt.Errorf(\"LLM upstream unreachable: %w\", err)\n    }\n    defer resp.Body.Close()\n    return nil\n}","typeGuard":null,"tryCatchPattern":"res, err := svc.LLMAutoStream(ctx, payload)\nif err != nil {\n    switch {\n    case errors.Is(err, context.Canceled):\n        return nil, fmt.Errorf(\"LLM stream cancelled by caller\")\n    case errors.Is(err, context.DeadlineExceeded):\n        return nil, fmt.Errorf(\"LLM stream timed out; extend deadline or retry\")\n    default:\n        return nil, fmt.Errorf(\"LLM stream transport failure: %w\", err)\n    }\n}","preventionTips":["Health-check the LLM endpoint at startup or via readiness probe before enabling AI codegen features.","Keep AutoCode base URL/AiPath in per-environment config and validate on boot.","Set explicit ctx deadlines with headroom for slow LLM first-token latency.","Always log the full wrapped error chain to distinguish DNS/TLS/timeout causes.","Implement retry with backoff and a degraded user-facing mode for provider outages."],"tags":["network","http","sse","llm","upstream"],"backgroundTag":"upstream-request-failed","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}