{"record":{"id":"d7293d6d7d48dcd1","repo":"chenhg5/cc-connect","slug":"gateway-response-decode-w","errorCode":null,"errorMessage":"gateway response decode: %w","messagePattern":"gateway response decode: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/qqbot/qqbot.go","lineNumber":702,"sourceCode":"\nfunc (p *Platform) getGatewayURL(token string) (string, error) {\n\treq, err := http.NewRequest(\"GET\", p.apiBase()+\"/gateway/bot\", nil)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treq.Header.Set(\"Authorization\", \"QQBot \"+token)\n\n\tresp, err := core.HTTPClient.Do(req)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"gateway request failed: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tvar result struct {\n\t\tURL string `json:\"url\"`\n\t}\n\tif err := json.NewDecoder(resp.Body).Decode(&result); err != nil {\n\t\treturn \"\", fmt.Errorf(\"gateway response decode: %w\", err)\n\t}\n\tif result.URL == \"\" {\n\t\treturn \"\", fmt.Errorf(\"empty gateway URL in response\")\n\t}\n\treturn result.URL, nil\n}\n\ntype wsPayload struct {\n\tOp int             `json:\"op\"`\n\tD  json.RawMessage `json:\"d,omitempty\"`\n\tS  *int64          `json:\"s,omitempty\"`\n\tT  string          `json:\"t,omitempty\"`\n}\n\nfunc (p *Platform) waitForHello(conn *websocket.Conn) error {\n\t_ = conn.SetReadDeadline(time.Now().Add(15 * time.Second))\n\tdefer func() { _ = conn.SetReadDeadline(time.Time{}) }()\n","sourceCodeStart":684,"sourceCodeEnd":720,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/qqbot/qqbot.go#L684-L720","documentation":"Returned when the HTTP response body from the QQ gateway endpoint cannot be decoded as JSON into the struct {url string}. Usually the body is HTML (error page), empty, or truncated instead of the expected JSON.","triggerScenarios":"json.NewDecoder(resp.Body).Decode fails because the gateway endpoint returned a non-JSON body — e.g. an HTML error page from a proxy, an empty body from a 5xx, or a WAF interception page.","commonSituations":"QQ returns an HTML rate-limit or WAF block page; a corporate proxy injects an auth page; server returns gzip/encoding the decoder can't handle transparently.","solutions":["Log the HTTP status code and raw body on decode failure to see what was actually returned","Check for proxy/WAF interference between the host and QQ","Verify the access token is valid — invalid auth often yields non-JSON error bodies","Retry; if persistent, capture the response body for a bug report"],"exampleFix":"// before\nif err := json.NewDecoder(resp.Body).Decode(&result); err != nil {\n    return \"\", fmt.Errorf(\"gateway response decode: %w\", err)\n}\n// after\nraw, _ := io.ReadAll(resp.Body)\nif resp.StatusCode != http.StatusOK {\n    return \"\", fmt.Errorf(\"gateway http %d: %s\", resp.StatusCode, raw)\n}\nif err := json.Unmarshal(raw, &result); err != nil {\n    return \"\", fmt.Errorf(\"gateway response decode: %w (body: %.200s)\", err, raw)\n}","handlingStrategy":"try-catch","validationCode":"if resp.StatusCode != http.StatusOK {\n    return fmt.Errorf(\"gateway returned %d\", resp.StatusCode)\n}","typeGuard":null,"tryCatchPattern":"body, readErr := io.ReadAll(resp.Body)\nif err := json.Unmarshal(body, &result); err != nil {\n    slog.Error(\"gateway non-JSON response\", \"status\", resp.StatusCode, \"body\", string(body), \"err\", readErr)\n    return retryOrFallback()\n}","preventionTips":["Always check status code before decoding JSON","Log raw response bodies on decode errors","Watch for proxy/WAF devices intercepting QQ traffic"],"tags":["json","http","qqbot","gateway"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}