{"record":{"id":"ec885a1ac37d55ba","repo":"prestodb/presto","slug":"iceberg-rest-auth-oauth2-requires-either-a-credent","errorCode":null,"errorMessage":"iceberg.rest.auth.oauth2 requires either a credential or a token","messagePattern":"iceberg\\.rest\\.auth\\.oauth2 requires either a credential or a token","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"presto-iceberg/src/main/java/com/facebook/presto/iceberg/rest/IcebergRestCatalogFactory.java","lineNumber":157,"sourceCode":"                () -> new IllegalStateException(\"iceberg.rest.uri must be set for REST catalog\")));\n\n        if (catalogConfig.isTlsEnabled()) {\n            properties.put(TLS_CONFIGURER_IMPL, PrestoRestTLSConfigurer.class.getName());\n            catalogConfig.getKeystorePath().ifPresent(path -> properties.put(KEYSTORE_PATH, path));\n            catalogConfig.getKeystorePassword().ifPresent(password -> properties.put(KEYSTORE_PASSWORD, password));\n            catalogConfig.getTruststorePath().ifPresent(path -> properties.put(TRUSTSTORE_PATH, path));\n            catalogConfig.getTruststorePassword().ifPresent(password -> properties.put(TRUSTSTORE_PASSWORD, password));\n        }\n\n        catalogConfig.getAuthenticationType().ifPresent(type -> {\n            if (type == OAUTH2) {\n                // The oauth2/tokens endpoint of the REST catalog spec has been deprecated and will\n                // be removed in Iceberg 2.0 (https://github.com/apache/iceberg/pull/10603)\n                // TODO auth server URI will eventually need to be made a required property\n                catalogConfig.getAuthenticationServerUri().ifPresent(authServerUri -> properties.put(OAUTH2_SERVER_URI, authServerUri));\n\n                if (!catalogConfig.credentialOrTokenExists()) {\n                    throw new IllegalStateException(\"iceberg.rest.auth.oauth2 requires either a credential or a token\");\n                }\n                catalogConfig.getCredential().ifPresent(credential -> properties.put(CREDENTIAL, credential));\n                catalogConfig.getToken().ifPresent(token -> properties.put(TOKEN, token));\n                catalogConfig.getScope().ifPresent(scope -> properties.put(SCOPE, scope));\n            }\n            if (type == BASIC) {\n                String basicAuthUsername = catalogConfig.getBasicAuthUsername().orElseThrow(\n                        () -> new IllegalStateException(\"iceberg.rest.auth.basic.username must be set for REST catalog when BASIC authentication is enabled\"));\n                String basicAuthPassword = catalogConfig.getBasicAuthPassword().orElseThrow(\n                        () -> new IllegalStateException(\"iceberg.rest.auth.basic.password must be set for REST catalog when BASIC authentication is enabled\"));\n                properties.put(AUTH_TYPE, AUTH_TYPE_BASIC);\n                properties.put(BASIC_USERNAME, basicAuthUsername);\n                properties.put(BASIC_PASSWORD, basicAuthPassword);\n            }\n        });\n\n        if (catalogConfig.isProxyEnabled()) {\n            properties.put(REST_PROXY_HOSTNAME, catalogConfig.getProxyHostname().get());","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-iceberg/src/main/java/com/facebook/presto/iceberg/rest/IcebergRestCatalogFactory.java#L139-L175","documentation":"IcebergRestCatalogFactory.builds catalog properties for the OAuth2 authentication type. The Iceberg REST spec's oauth2/tokens endpoint is deprecated, so the connector requires credentials (client id/secret) or a bearer token to be supplied up front. If the OAUTH2 auth type is selected but catalogConfig.credentialOrTokenExists() is false, the factory fails fast with IllegalStateException.","triggerScenarios":"Configuring an Iceberg REST catalog with iceberg.rest.auth.type=OAUTH2 (or oauth2 defaults applying) while providing neither a credential nor a token in the catalog properties.","commonSituations":"Setting iceberg.rest.auth.oauth2.server-uri (the deprecated auth-server flow) but forgetting iceberg.rest.auth.credential or token; migrating from an older connector version that could fetch tokens from the server URI; partially filled catalog config files; secrets injected by deployment tooling not reaching the properties map.","solutions":["Set iceberg.rest.auth.credential=<client_id>:<client_secret> in the catalog properties","Or set iceberg.rest.auth.token=<bearer-token>","Remove the auth-server-uri-only configuration and supply the credential/token the REST server actually accepts","Check that secret injection (env vars, keystore, config service) is populating the property at deploy time"],"exampleFix":"// before\niceberg.rest.auth.type=OAUTH2\niceberg.rest.auth.oauth2.server-uri=https://auth.example.com/token\n// after\niceberg.rest.auth.type=OAUTH2\niceberg.rest.auth.credential=client123:secret456","handlingStrategy":"validation","validationCode":"// at deploy/config time, before creating the REST catalog\nif (authType == OAUTH2 && credential == null && token == null) {\n    throw new IllegalStateException(\"Set iceberg.rest.auth.credential or iceberg.rest.auth.token\");\n}","typeGuard":"boolean hasOauth2Secret(Map<String, String> props) {\n    return props.containsKey(\"iceberg.rest.auth.credential\")\n        || props.containsKey(\"iceberg.rest.auth.token\");\n}","tryCatchPattern":"try {\n    IcebergRestCatalogFactory.create(properties);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"requires either a credential or a token\")) {\n        // load credential/token from secret store and retry config\n    }\n}","preventionTips":["Always pair auth type OAUTH2 with credential or token in catalog properties","Verify secret-injection pipelines actually populate the property at runtime","Remember server-uri alone no longer suffices; the token endpoint is deprecated in Iceberg 2.0","Smoke-test catalog creation in CI with the same property set used in production"],"tags":["iceberg","rest-catalog","oauth2","configuration"],"backgroundTag":"missing-oauth2-credential","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}