{"record":{"id":"f1173d763c396910","repo":"chenhg5/cc-connect","slug":"qqbot-failed-to-get-access-token-w","errorCode":null,"errorMessage":"qqbot: failed to get access token: %w","messagePattern":"qqbot: failed to get access token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"platform/qqbot/qqbot.go","lineNumber":196,"sourceCode":"\t\tshareSessionInChannel: shareSessionInChannel,\n\t\tintents:               intents,\n\t\tmarkdownSupport:       markdownSupport,\n\t\tmessageCachePath:      qqbotMessageCachePath(dataDir),\n\t}, nil\n}\n\nfunc (p *Platform) Name() string { return \"qqbot\" }\n\n// Start connects to the QQ Bot gateway and begins receiving events.\nfunc (p *Platform) Start(handler core.MessageHandler) error {\n\tp.handler = handler\n\tif err := p.loadMessageCache(); err != nil {\n\t\tslog.Warn(\"qqbot: load message cache failed\", \"error\", err)\n\t}\n\n\t// Get initial access token\n\tif err := p.refreshToken(); err != nil {\n\t\treturn fmt.Errorf(\"qqbot: failed to get access token: %w\", err)\n\t}\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tp.ctx = ctx\n\tp.cancel = cancel\n\n\tif err := p.connectGateway(ctx); err != nil {\n\t\tcancel()\n\t\treturn fmt.Errorf(\"qqbot: failed to connect gateway: %w\", err)\n\t}\n\n\tslog.Info(\"qqbot: connected to QQ Bot gateway\", \"sandbox\", p.sandbox)\n\treturn nil\n}\n\n// Reply sends a message as a reply to an incoming message.\nfunc (p *Platform) Reply(ctx context.Context, replyCtx any, content string) error {\n\treturn p.Send(ctx, replyCtx, content)","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/qqbot/qqbot.go#L178-L214","documentation":"Start() calls refreshToken() to obtain the initial access token from the QQ Bot auth endpoint before connecting the gateway. If the token request fails (auth error, network failure, non-200 response), Start aborts and wraps the underlying error with this message. Without a valid token no further API calls can succeed, so startup is halted.","triggerScenarios":"Calling Start() when the app_id/app_secret are wrong (auth endpoint rejects the exchange), the host cannot reach the QQ Bot auth API (offline, firewall, DNS), the sandbox flag does not match the credentials, or refreshToken's HTTP request returns an error/non-2xx.","commonSituations":"Rotated or revoked app secret in a production config; running with sandbox=true but production credentials (or vice versa); corporate proxy blocking api.sgroup.qq.com; QQ开放平台 app not yet approved/published; transient network blip at daemon boot.","solutions":["Verify app_id/app_secret are correct and still valid on the QQ Bot open platform console.","Match the sandbox option to the credential environment: sandbox=true only for test-bed credentials.","Check outbound network access to the QQ Bot auth endpoint (proxy/firewall/DNS); set proxy env vars if needed.","Retry Start() with backoff if the failure is transient (network 5xx/timeout).","Inspect the wrapped inner error (%w) for the exact HTTP status / auth message returned by the API."],"exampleFix":"// before\nif err := platform.Start(ctx); err != nil { slog.Error(\"start failed\", \"error\", err); os.Exit(1) }\n// after\nvar err error\nfor i := 0; i < 3; i++ {\n    if err = platform.Start(ctx); err == nil || !strings.Contains(err.Error(), \"failed to get access token\") {\n        break\n    }\n    time.Sleep(time.Duration(1<<i) * time.Second)\n}\nif err != nil { slog.Error(\"start failed\", \"error\", err); os.Exit(1) }","handlingStrategy":"retry","validationCode":"// Pre-flight: confirm auth endpoint reachability before Start\nreq, _ := http.NewRequestWithContext(ctx, http.MethodPost, authURL, strings.NewReader(\"\"))\nresp, err := http.DefaultClient.Do(req)\nif err != nil { return fmt.Errorf(\"auth endpoint unreachable: %w\", err) }\nresp.Body.Close()","typeGuard":null,"tryCatchPattern":"if err := p.Start(ctx); err != nil {\n    if strings.Contains(err.Error(), \"failed to get access token\") {\n        // inspect errors.Unwrap(err) for HTTP status; retry with backoff\n    }\n}","preventionTips":["Rotate app secrets centrally and redeploy configs, never edit credentials in-place at runtime.","Keep sandbox flag and credential set in the same config block so they cannot drift.","Monitor token-refresh failures with an alert on the wrapped auth error.","Test outbound connectivity to QQ API hosts from the deployment environment."],"tags":["qqbot","authentication","network","startup"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}