{"record":{"id":"0c7dbfe22e933952","repo":"bytebase/bytebase","slug":"failed-to-test-auth-error-v","errorCode":null,"errorMessage":"failed to test auth, error: %v","messagePattern":"failed to test auth, error: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/plugin/webhook/slack/app.go","lineNumber":87,"sourceCode":"\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to send request\")\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn errors.Errorf(\"received non-200 status code %d\", resp.StatusCode)\n\t}\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to read body\")\n\t}\n\tvar res authTestResponse\n\tif err := json.Unmarshal(body, &res); err != nil {\n\t\treturn errors.Wrapf(err, \"failed to unmarshal\")\n\t}\n\tif !res.OK {\n\t\treturn errors.Errorf(\"failed to test auth, error: %v\", res.Error)\n\t}\n\n\tscopes := resp.Header.Get(\"x-oauth-scopes\")\n\thasScope := map[string]bool{}\n\tfor _, s := range strings.Split(scopes, \",\") {\n\t\thasScope[s] = true\n\t}\n\tvar missScope []string\n\tfor _, s := range []string{\"users:read\", \"users:read.email\", \"channels:manage\", \"groups:write\", \"im:write\", \"chat:write\", \"mpim:write\"} {\n\t\tif !hasScope[s] {\n\t\t\tmissScope = append(missScope, s)\n\t\t}\n\t}\n\tif len(missScope) > 0 {\n\t\treturn errors.Errorf(\"missing the following scopes: %s\", strings.Join(missScope, \",\"))\n\t}\n\n\treturn nil","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/webhook/slack/app.go#L69-L105","documentation":"Slack's auth.test responded 200 with parseable JSON but ok:false, meaning Slack rejected the token. The surfaced Slack error string (e.g. invalid_auth, account_inactive, token_revoked) identifies why. This is the definitive signal that the configured Slack bot token is not usable.","triggerScenarios":"authTest reads res.OK == false after a successful call — token invalid/deleted, bot app uninstalled, workspace deactivated, or token type lacking required scopes (subsequent scope check on x-oauth-scopes can also gate access).","commonSituations":"Token rotated/revoked in Slack admin console but old value still stored in Bytebase config; bot app removed from the workspace; pasting a user token (xoxp) where a bot token (xoxb) is required; Slack app not reinstalled after scope changes.","solutions":["Read the Slack error in the message: invalid_auth/token_revoked means regenerate the token; account_inactive means the account/bot was disabled.","Create/copy a fresh bot token from the Slack app's OAuth & Permissions page (xoxb-...) and update the Bytebase webhook configuration.","Reinstall the Slack app to the workspace if it was uninstalled or scopes changed.","Confirm required chat:write scope is present in the token's scopes (the code also checks x-oauth-scopes).","Re-run the connection test in Bytebase after updating the token."],"exampleFix":"// before\n\"token\": \"xoxb-1234-old-revoked-token\"\n// after: fresh token from Slack app config\n\"token\": \"xoxb-5678-9012-current-valid-token\"","handlingStrategy":"validation","validationCode":"// validate the token before storing it\nreq, _ := http.NewRequest(\"POST\", \"https://slack.com/api/auth.test\", nil)\nreq.Header.Set(\"Authorization\", \"Bearer \"+token)\nresp, err := http.DefaultClient.Do(req)\nif err != nil { return err }\nvar r struct{ OK bool `json:\"ok\"`; Error string `json:\"error\"` }\njson.NewDecoder(resp.Body).Decode(&r)\nif !r.OK { return fmt.Errorf(\"token rejected by Slack: %s\", r.Error) }","typeGuard":"func tokenUsable(res authTestResponse) bool {\n    return res.OK\n}","tryCatchPattern":"if err := p.authTest(ctx); err != nil {\n    if strings.Contains(err.Error(), \"invalid_auth\") || strings.Contains(err.Error(), \"token_revoked\") {\n        // surface 're-enter Slack bot token' to the user\n    } else if strings.Contains(err.Error(), \"account_inactive\") {\n        // surface 'reinstall the Slack app'\n    }\n}","preventionTips":["Re-test the Slack connection whenever tokens are rotated in Slack admin.","Always use bot tokens (xoxb-) unless user context is explicitly required.","Reinstall the Slack app after scope changes and re-run auth.test.","Alert on auth.test failures so expired tokens are caught before delivery breaks."],"tags":["slack","auth","token","api"],"backgroundTag":"authentication-required","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}