{"record":{"id":"1387963fbc1dbcc2","repo":"chenhg5/cc-connect","slug":"empty-gateway-url-in-response","errorCode":null,"errorMessage":"empty gateway URL in response","messagePattern":"empty gateway URL in response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/qqbot/qqbot.go","lineNumber":705,"sourceCode":"\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\n\tvar msg wsPayload\n\tif err := conn.ReadJSON(&msg); err != nil {\n\t\treturn fmt.Errorf(\"waiting for hello: %w\", err)","sourceCodeStart":687,"sourceCodeEnd":723,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/qqbot/qqbot.go#L687-L723","documentation":"QQ bot gateway fetch guard: the gateway endpoint responded with valid JSON but an empty url field, leaving no WebSocket endpoint to connect to — a server-side misconfiguration or regional outage rather than a client error.","triggerScenarios":"QQ API returns 200 with JSON lacking a populated url field — typically due to an expired/invalid access token or an API behavior change.","commonSituations":"Access token expired between fetch and use; appid/secret misconfigured so token is nominal; QQ API version change altering the response shape.","solutions":["Re-fetch the access token and confirm it is non-empty before calling the gateway endpoint","Verify appid/secret in config.toml are correct for the QQ bot app","Log the full gateway response to inspect unexpected fields","Check QQ open-platform docs/changelog for gateway API changes"],"exampleFix":"// before\nif result.URL == \"\" {\n    return \"\", fmt.Errorf(\"empty gateway URL in response\")\n}\n// after\nif result.URL == \"\" {\n    return \"\", fmt.Errorf(\"empty gateway URL in response (status=%d)\", resp.StatusCode)\n}","handlingStrategy":"validation","validationCode":"if token == \"\" {\n    return errors.New(\"access token missing before gateway fetch\")\n}","typeGuard":null,"tryCatchPattern":"gwURL, err := p.getGatewayURL()\nif err != nil {\n    if strings.Contains(err.Error(), \"empty gateway URL\") {\n        _ = p.refreshAccessToken()\n        gwURL, err = p.getGatewayURL()\n    }\n    if err != nil { return err }\n}","preventionTips":["Refresh the access token before each gateway fetch or on 401","Validate appid/secret at startup with a doctor command","Log the full gateway JSON when url is empty"],"tags":["qqbot","gateway","empty-response"],"backgroundTag":"empty-api-response","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"}