{"record":{"id":"1ca88b207fe8ca58","repo":"justauth/JustAuth","slug":"error-response-metadata-messages","errorCode":null,"errorMessage":"${error}; ${response_metadata.messages}","messagePattern":"\\$\\{error\\}; \\$\\{response_metadata\\.messages\\}","errorType":"exception","errorClass":"AuthException","httpStatus":null,"severity":"error","filePath":"src/main/java/me/zhyd/oauth/request/AuthSlackRequest.java","lineNumber":106,"sourceCode":"        return AuthResponse.builder().code(status.getCode()).msg(status.getMsg()).build();\n    }\n\n    /**\n     * 检查响应内容是否正确\n     *\n     * @param object 请求响应内容\n     */\n    private void checkResponse(JSONObject object) {\n        if (!object.getBooleanValue(\"ok\")) {\n            String errorMsg = object.getString(\"error\");\n            if (object.containsKey(\"response_metadata\")) {\n                JSONArray array = object.getJSONObject(\"response_metadata\").getJSONArray(\"messages\");\n                if (null != array && array.size() > 0) {\n                    errorMsg += \"; \" + String.join(\",\", array.toArray(new String[0]));\n                }\n            }\n\n            throw new AuthException(errorMsg);\n        }\n    }\n\n    @Override\n    public String userInfoUrl(AuthToken authToken) {\n        return UrlBuilder.fromBaseUrl(source.userInfo())\n            .queryParam(\"user\", authToken.getUid())\n            .build();\n    }\n\n    /**\n     * 返回带{@code state}参数的授权url，授权回调时会带上这个{@code state}\n     *\n     * @param state state 验证授权流程的参数，可以防止csrf\n     * @return 返回授权地址\n     */\n    @Override\n    public String authorize(String state) {","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/justauth/JustAuth/blob/694bbf1b010d93404e3bfb4824d90e9ddfaebebb/src/main/java/me/zhyd/oauth/request/AuthSlackRequest.java#L88-L124","documentation":"AuthSlackRequest.checkResponse inspects the Slack Web API envelope: every Slack response carries an `ok` boolean. When ok is false, JustAuth throws AuthException whose message is the `error` field (Slack machine-readable error code such as 'invalid_auth', 'not_authed') plus any human-readable hints from response_metadata.messages joined with commas. Note this exception has no error code — only a message.","triggerScenarios":"Any Slack API call made by AuthSlackRequest (getAccessToken via oauth.access, getUserInfo via users.identity) after the user installation is broken: invalid/revoked bot token, wrong client_id/client_secret on code exchange, missing identity scope, or redirect_uri mismatch.","commonSituations":"Rotating Slack app credentials without updating AuthConfig; the Slack app was reinstalled and the old token was invalidated; requesting 'identity.basic' but the app only has 'identity:basic' style scope naming issues; workspace admin uninstalled the app.","solutions":["Read the leading token of the message: Slack error codes are enumerated at api.slack.com/methods — 'invalid_auth' means bad token, 'invalid_client_secret'/'bad_verification_code' mean code exchange config mismatch.","Verify clientId/clientSecret in AuthConfig match the current Slack app (Basic Information > App Credentials).","Confirm the user scope includes identity.basic (Slack Sign-In requires user tokens, not bot tokens).","If the app was reinstalled, have the user re-authorize via authorize(state) to mint fresh tokens."],"exampleFix":"// before: config with stale secret\nnew AuthSlackRequest(AuthConfig.builder().clientIdId? ...);\n\n// after: align credentials + user scope\nAuthConfig cfg = AuthConfig.builder()\n    .clientId(\"current-client-id\")\n    .clientSecret(\"current-client-secret\")\n    .redirectUri(\"https://app.example.com/oauth/slack/callback\")\n    .scopes(AuthSlackScope.IDENTITY_BASIC_USER)\n    .build();","handlingStrategy":"try-catch","validationCode":"// pre-flight: cheap API call to confirm creds before full flow\n// (Slack auth.test with the bot token) — verify clientId/clientSecret non-empty\nif (StringUtils.isAnyEmpty(config.getClientId(), config.getClientSecret())) {\n    throw new IllegalArgumentException(\"Slack clientId/clientSecret required\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    AuthUser user = request.login(callback);\n} catch (AuthException e) {\n    String msg = String.valueOf(e.getMessage());\n    if (msg.startsWith(\"invalid_auth\") || msg.startsWith(\"not_authed\")) {\n        // token revoked/rotated: force re-consent\n        redirect(request.authorize(freshState()));\n    } else throw e;\n}","preventionTips":["Store Slack app credentials in a config service and rotate them atomically with deploys.","Subscribe to Slack 'app_uninstalled' / 'tokens_revoked' events to drop stored tokens immediately.","Request the identity.basic user scope explicitly in AuthConfig."],"tags":["justauth","slack","oauth","api-error","invalid-token"],"backgroundTag":null,"analyzedSha":"694bbf1b010d93404e3bfb4824d90e9ddfaebebb","analyzedAt":"2026-08-14T15:16:59.945Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}