{"record":{"id":"81b97918c4a90d5b","repo":"flipped-aurora/gin-vue-admin","slug":"status-d-content-type-s-body-s-err","errorCode":null,"errorMessage":"解析大模型响应失败: status=%d content-type=%s body=%s err=%w","messagePattern":"解析大模型响应失败: status=(.+?) content-type=(.+?) body=(.+?) err=%w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/auto_code_llm.go","lineNumber":50,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"调用上游大模型服务失败: %w\", err)\n\t}\n\tdefer res.Body.Close()\n\n\tbody, err := io.ReadAll(res.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"读取大模型响应失败: %w\", err)\n\t}\n\n\tbodyPreview := previewResponseBody(body)\n\tcontentType := res.Header.Get(\"Content-Type\")\n\tif res.StatusCode < 200 || res.StatusCode >= 300 {\n\t\treturn nil, fmt.Errorf(\"上游大模型服务返回非 2xx: status=%d content-type=%s body=%s\", res.StatusCode, contentType, bodyPreview)\n\t}\n\n\tvar resStruct commonResp.Response\n\tif err = json.Unmarshal(body, &resStruct); err != nil {\n\t\treturn nil, fmt.Errorf(\"解析大模型响应失败: status=%d content-type=%s body=%s err=%w\", res.StatusCode, contentType, bodyPreview, err)\n\t}\n\n\tif resStruct.Code != commonResp.SUCCESS {\n\t\treturn nil, fmt.Errorf(\"大模型服务返回业务错误: code=%d msg=%s body=%s\", resStruct.Code, resStruct.Msg, bodyPreview)\n\t}\n\n\treturn resStruct.Data, nil\n}\n\nfunc (s *AutoCodeService) LLMAutoStream(ctx context.Context, llm common.JSONMap) (*http.Response, error) {\n\tpath, err := buildLLMAutoPath(llm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tpayload := cloneLLMAutoJSONMap(llm)\n\tresponseMode := strings.ToLower(strings.TrimSpace(fmt.Sprintf(\"%v\", payload[\"response_mode\"])))\n\tif responseMode == \"\" {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/auto_code_llm.go#L32-L68","documentation":"Even with a 2xx status, LLMAuto json.Unmarshals the body into commonResp.Response; if the body is not valid JSON or its shape doesn't fit, this error reports status, content-type, body preview, and the unmarshal error. It catches non-JSON or unexpected response formats from the upstream.","triggerScenarios":"The upstream returns 2xx but the body cannot be unmarshaled: HTML error/login pages behind a mis-URL'd gateway, plain-text responses, SSE/partial data returned to a non-stream call, or a JSON shape with different field types (e.g. code as string).","commonSituations":"Pointing the LLM URL at a proxy/landing page, provider returning streaming (text/event-stream) when response_mode wasn't set correctly, provider SDK contract change, Content-Type application/json but vendor-specific envelope.","solutions":["Check the body preview and Content-Type in the error — if it's HTML, the URL is wrong (proxy/login page)","If it's text/event-stream or partial data, use LLMAutoStream instead of LLMAuto","Compare the actual JSON envelope with commonResp.Response fields (code/data/msg) and adapt config or parsing","Verify response_mode/headers in the llm config match what the provider expects for non-streaming calls"],"exampleFix":"// before: blind unmarshal into fixed envelope\nvar resStruct commonResp.Response\nif err = json.Unmarshal(body, &resStruct); err != nil { return nil, ... }\n// after: guard on content type first\nif strings.Contains(contentType, \"text/event-stream\") {\n    return nil, fmt.Errorf(\"上游返回流式响应，请使用流式接口\")\n}\nvar resStruct commonResp.Response\nif err = json.Unmarshal(body, &resStruct); err != nil { return nil, ... }","handlingStrategy":"type-guard","validationCode":"ct := res.Header.Get(\"Content-Type\")\nif !strings.Contains(ct, \"application/json\") {\n    return fmt.Errorf(\"期望 JSON 响应，实际 Content-Type: %s\", ct)\n}\nif !json.Valid(body) {\n    return fmt.Errorf(\"响应不是合法 JSON: %s\", previewResponseBody(body))\n}","typeGuard":"func isLLMEnvelope(b []byte) bool {\n    var probe struct {\n        Code interface{} `json:\"code\"`\n    }\n    return json.Unmarshal(b, &probe) == nil\n}","tryCatchPattern":"data, err := svc.LLMAuto(ctx, llmCfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"解析大模型响应失败\") {\n        // fall back to streaming endpoint or return contract-mismatch diagnostics\n    }\n    return err\n}","preventionTips":["Use the streaming API (LLMAutoStream) when response_mode is streaming; don't send stream responses to the non-stream parser","Verify the upstream URL returns your API, not a proxy or login page (HTML bodies)","Keep the response envelope contract documented and test it against the live provider","Check Content-Type before unmarshaling"],"tags":["json","parsing","llm","api-contract"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}