{"record":{"id":"18ae36cbeb93e065","repo":"apache/iceberg","slug":"invalid-credential","errorCode":null,"errorMessage":"Invalid credential: ","messagePattern":"Invalid credential: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/rest/auth/OAuth2Util.java","lineNumber":302,"sourceCode":"    }\n    formData.putAll(optionalParams);\n\n    return formData.buildKeepingLast();\n  }\n\n  private static Pair<String, String> parseCredential(String credential) {\n    Preconditions.checkNotNull(credential, \"Invalid credential: null\");\n    List<String> parts = CREDENTIAL_SPLITTER.splitToList(credential);\n    switch (parts.size()) {\n      case 2:\n        // client ID and client secret\n        return Pair.of(parts.get(0), parts.get(1));\n      case 1:\n        // client secret\n        return Pair.of(null, parts.get(0));\n      default:\n        // this should never happen because the credential splitter is limited to 2\n        throw new IllegalArgumentException(\"Invalid credential: \" + credential);\n    }\n  }\n\n  private static Map<String, String> clientCredentialsRequest(\n      String credential, List<String> scopes, Map<String, String> optionalOAuthParams) {\n    Pair<String, String> credentialPair = parseCredential(credential);\n    return clientCredentialsRequest(\n        credentialPair.first(), credentialPair.second(), scopes, optionalOAuthParams);\n  }\n\n  private static Map<String, String> clientCredentialsRequest(\n      String clientId,\n      String clientSecret,\n      List<String> scopes,\n      Map<String, String> optionalOAuthParams) {\n    ImmutableMap.Builder<String, String> formData = ImmutableMap.builder();\n    formData.put(GRANT_TYPE, CLIENT_CREDENTIALS);\n    if (clientId != null) {","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/rest/auth/OAuth2Util.java#L284-L320","documentation":"Thrown by OAuth2Util.parseCredential when a credential string splits into more than 2 colon-separated parts. A valid credential is 'client-id:client-secret' or just 'client-secret'; anything with multiple extra colons is invalid.","triggerScenarios":"Passing a credential like 'id:secret:extra' (or an unescaped colon inside the secret) to OAuth2Util.credentialPair / client-credentials token exchange via catalog OAuth2 config.","commonSituations":"Secrets containing raw colons that were not URL-encoded; concatenating config values incorrectly; pasting credentials with trailing segments from a keyfile.","solutions":["Remove extra colons — supply only client-id:client-secret or client-secret alone","URL-encode colons inside the client secret (e.g. %3A) if the provider requires them","Generate a fresh credential without special characters if the provider allows","Split correctly: the splitter is limited to 2 parts, so only one colon is allowed"],"exampleFix":"// before\nconf.put(\"rest.credential\", \"client1:sec:ret\");\n// after\nconf.put(\"rest.credential\", \"client1:sec%3Aret\"); // or use a secret without colons","handlingStrategy":"validation","validationCode":"// validate credential format before configuring the catalog\nString credential = \"id:secret\";\nboolean valid = credential.indexOf(':') == credential.lastIndexOf(':');\nif (!valid) throw new IllegalArgumentException(\"Credential must be 'client-id:client-secret' or 'client-secret'\");","typeGuard":"boolean isValidCredential(String credential) {\n  return credential != null && credential.indexOf(':') == credential.lastIndexOf(':');\n}","tryCatchPattern":"try { Pair<String,String> p = OAuth2Util.parseCredential(credential); }\ncatch (IllegalArgumentException e) { /* fix credential format: at most one colon */ }","preventionTips":["URL-encode colons in secrets (%3A) when providers require them","Validate credential format at config load time","Never concatenate extra segments into the credential property"],"tags":["oauth2","authentication","format","rest-catalog"],"backgroundTag":"invalid-argument-format","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"}