{"record":{"id":"d428c7ec23be447e","repo":"apache/iceberg","slug":"not-authorized-s-s","errorCode":null,"errorMessage":"Not authorized: %s: %s","messagePattern":"Not authorized: (.+?): (.+?)","errorType":"exception","errorClass":"NotAuthorizedException","httpStatus":401,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java","lineNumber":379,"sourceCode":"  private static class OAuthErrorHandler extends ErrorHandler {\n    private static final ErrorHandler INSTANCE = new OAuthErrorHandler();\n\n    @Override\n    public ErrorResponse parseResponse(int code, String json) {\n      try {\n        return OAuthErrorResponseParser.fromJson(code, json);\n      } catch (Exception x) {\n        LOG.warn(\"Unable to parse error response\", x);\n      }\n      return ErrorResponse.builder().responseCode(code).withMessage(json).build();\n    }\n\n    @Override\n    public void accept(ErrorResponse error) {\n      if (error.type() != null) {\n        switch (error.type()) {\n          case OAuth2Properties.INVALID_CLIENT_ERROR:\n            throw new NotAuthorizedException(\n                \"Not authorized: %s: %s\", error.type(), error.message());\n          case OAuth2Properties.INVALID_REQUEST_ERROR:\n          case OAuth2Properties.INVALID_GRANT_ERROR:\n          case OAuth2Properties.UNAUTHORIZED_CLIENT_ERROR:\n          case OAuth2Properties.UNSUPPORTED_GRANT_TYPE_ERROR:\n          case OAuth2Properties.INVALID_SCOPE_ERROR:\n            throw new BadRequestException(\n                \"Malformed request: %s: %s\", error.type(), error.message());\n        }\n      }\n      throw createRESTException(error);\n    }\n  }\n}\n","sourceCodeStart":361,"sourceCodeEnd":394,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/rest/ErrorHandlers.java#L361-L394","documentation":"The OAuth2 error handler (OAuth2Client's error handler) maps an OAuth token endpoint response with error type 'invalid_client' to NotAuthorizedException. The token server rejected the client credentials — the client ID/secret or token is invalid. Message includes the OAuth error type and description.","triggerScenarios":"Token exchange call to the OAuth2/token endpoint (via OAuth2Util or token fetch in the REST client) returned HTTP 400 with error=invalid_client, meaning client authentication failed.","commonSituations":"Wrong or rotated client secret in catalog properties, typos in 'credential' (client-id:client-secret), using a revoked client, or sending a client credential where a token is required.","solutions":["Verify the 'credential' property format is exactly 'client-id:client-secret' and both are correct","Confirm the client credentials are still active with your OAuth2/token issuer (not rotated or revoked)","If using a static token, verify the token itself is valid and unexpired","Check the oauth2-server-uri points at the correct token endpoint"],"exampleFix":"// before\nprops.put(\"credential\", \"myclient wrongsecret\"); // wrong separator/secret\n// after\nprops.put(\"credential\", \"myclient:correct-secret\"); // client-id:client-secret","handlingStrategy":"validation","validationCode":"String credential = props.get(\"credential\");\nif (credential != null && credential.indexOf(':') <= 0) {\n  throw new IllegalArgumentException(\"credential must be 'client-id:client-secret'\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  String token = OAuth2Util.fetchToken(client, authConfig);\n} catch (NotAuthorizedException e) {\n  throw new IllegalStateException(\"Invalid client credentials: \" + e.getMessage(), e);\n}","preventionTips":["Validate credential format client-id:client-secret before building the catalog","Sync credentials from a secret manager rather than hardcoding","Test token exchange at startup, not on first catalog call"],"tags":["rest","oauth2","authentication","token-exchange"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}