{"record":{"id":"bd8b535ca2a6b475","repo":"sipeed/picoclaw","slug":"failed-to-get-bot-user-w","errorCode":null,"errorMessage":"failed to get bot user: %w","messagePattern":"failed to get bot user: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/channels/discord/discord.go","lineNumber":115,"sourceCode":"\t\ttypingStop:  make(map[string]chan struct{}),\n\t\tbus:         bus,\n\t\tvoiceSSRC:   make(map[string]map[uint32]string),\n\t}\n\tch.playTTSFn = ch.playTTS\n\tch.ttsVoiceFn = ch.voiceConnectionForTTS\n\tch.progress = channels.NewToolFeedbackAnimator(ch.EditMessage)\n\treturn ch, nil\n}\n\nfunc (c *DiscordChannel) Start(ctx context.Context) error {\n\tlogger.InfoC(\"discord\", \"Starting Discord bot\")\n\n\tc.ctx, c.cancel = context.WithCancel(ctx)\n\n\t// Get bot user ID before opening session to avoid race condition\n\tbotUser, err := c.session.User(\"@me\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get bot user: %w\", err)\n\t}\n\tc.botUserID = botUser.ID\n\n\tc.session.AddHandler(c.handleMessage)\n\n\tgo c.listenVoiceControl(c.ctx)\n\n\tif err := c.session.Open(); err != nil {\n\t\treturn fmt.Errorf(\"failed to open discord session: %w\", err)\n\t}\n\n\tc.SetRunning(true)\n\n\tlogger.InfoCF(\"discord\", \"Discord bot connected\", map[string]any{\n\t\t\"username\": botUser.Username,\n\t\t\"user_id\":  botUser.ID,\n\t})\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/discord/discord.go#L97-L133","documentation":"Start() calls session.User(\"@me\") (GET /users/@me) before opening the gateway to capture botUserID and avoid a race. This error means that REST call failed: invalid/expired token (401), network or proxy failure reaching discord.com, or a Discord API error. The underlying discordgo error is wrapped with %w.","triggerScenarios":"Token was regenerated in the Developer Portal (old token revoked), token typo/truncated, HTTP(S)_PROXY env or cfg.Proxy pointing to an unreachable proxy (applyDiscordProxy installs it on the session client), DNS/firewall blocking discord.com, Discord 5xx.","commonSituations":"Token reset in the portal but config not updated, container without network egress, proxy env vars leaking into the process, transient Discord API issues at startup.","solutions":["Verify the token independently: curl -H 'Authorization: Bot <token>' https://discord.com/api/v10/users/@me should return 200 with the bot JSON","Fix proxy configuration: valid scheme in discord.proxy (http/https/socks5) or unset broken HTTP_PROXY/HTTPS_PROXY","Check network egress/DNS from the host and retry Start on transient failures","If 401, create a new token in the Developer Portal and update config"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-flight the token before Start()\nreq, _ := http.NewRequest(http.MethodGet, \"https://discord.com/api/v10/users/@me\", nil)\nreq.Header.Set(\"Authorization\", \"Bot \"+cfg.Token.String())\nresp, err := http.DefaultClient.Do(req)\nif err != nil || resp.StatusCode != 200 {\n    return fmt.Errorf(\"discord token invalid or discord unreachable: %v / %d\", err, respStatus(resp))\n}","typeGuard":null,"tryCatchPattern":"if err := ch.Start(ctx); err != nil {\n    if strings.Contains(err.Error(), \"failed to get bot user\") {\n        // 401 => bad token (fix config); network error => fix egress/proxy, then retry\n    }\n    return err\n}","preventionTips":["Validate the bot token with a users/@me REST call before starting the channel","Keep proxy config valid — an unreachable HTTP(S)_PROXY breaks this REST call even with a good token","When regenerating a token in the Developer Portal, update config immediately (old tokens are revoked)","Retry Start with backoff only after excluding auth failure (401)"],"tags":["discord","authentication","rest","startup","proxy"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}