{"record":{"id":"7ef6aeb128db54c2","repo":"apache/pulsar","slug":"illegal-base64-character-or-key-file-keyconfurl","errorCode":null,"errorMessage":"Illegal base64 character or Key file ${keyConfUrl} doesn't exist","messagePattern":"Illegal base64 character or Key file (.+?) doesn't exist","errorType":"validation","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/utils/AuthTokenUtils.java","lineNumber":131,"sourceCode":"                if (keyConfUrl.startsWith(\"file:\")) {\n                    keyConfUrl = keyConfUrl.trim();\n                }\n                return IOUtils.toByteArray(URL.createURL(keyConfUrl));\n            } catch (IOException e) {\n                throw e;\n            } catch (Exception e) {\n                throw new IOException(e);\n            }\n        } else if (Files.exists(Paths.get(keyConfUrl))) {\n            // Assume the key content was passed in a valid file path\n            return Files.readAllBytes(Paths.get(keyConfUrl));\n        } else if (Base64.isBase64(keyConfUrl.getBytes())) {\n            // Assume the key content was passed in base64\n            try {\n                return Decoders.BASE64.decode(keyConfUrl);\n            } catch (DecodingException e) {\n                String msg = \"Illegal base64 character or Key file \" + keyConfUrl + \" doesn't exist\";\n                throw new IOException(msg, e);\n            }\n        } else {\n            String msg = \"Secret/Public Key file \" + keyConfUrl + \" doesn't exist\";\n            throw new IllegalArgumentException(msg);\n        }\n    }\n}\n","sourceCodeStart":113,"sourceCodeEnd":139,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/utils/AuthTokenUtils.java#L113-L139","documentation":"readKeyFromUrl treats the configured value as: a file path/URL, or if it looks like pure base64, inline base64 key material. When the value is base64-shaped but Decoders.BASE64.decode still fails (illegal characters after the cheap isBase64 check), it wraps the DecodingException in this IOException.","triggerScenarios":"Setting tokenSecretKey/tokenPublicKey to an inline value that starts out base64-like (passes Base64.isBase64 on getBytes) but contains characters the strict decoder rejects — e.g. whitespace/newlines, URL-encoded characters, or mixed encodings.","commonSituations":"YAML/properties value with line wrapping or trailing newline inside the base64 secret; quoting issues that inject spaces; using a `data:` URL or `file:` prefix in a value that was meant to be inline base64.","solutions":["Re-encode the key with standard base64 (no whitespace, no newlines) and paste it as a single line.","If you meant a file, check the path: the file must exist, otherwise this code path wouldn't be chosen — verify no stray characters make the path look like base64.","Decode the string yourself with `Base64.getDecoder().decode()` in a shell/test to find the offending character."],"exampleFix":"// before\nString keyConfUrl = \"MIIBIjANBgkq...\\n  more==\"; // embedded whitespace/newlines\n// after\nString keyConfUrl = key.replace(\"\\n\", \"\").replace(\" \", \"\").trim(); // single clean base64 line","handlingStrategy":"validation","validationCode":"String clean = value.replaceAll(\"\\\\s\", \"\");\nif (!clean.matches(\"[A-Za-z0-9+/]*={0,2}\")) throw new IllegalArgumentException(\"not clean base64\");\njava.util.Base64.getDecoder().decode(clean); // strict round-trip check","typeGuard":"boolean isCleanBase64(String s) { return s != null && s.replaceAll(\"\\\\s\", \"\").matches(\"[A-Za-z0-9+/]+={0,2}\"); }","tryCatchPattern":"try { byte[] key = AuthTokenUtils.readKeyFromUrl(cfg); } catch (IOException e) { throw new IllegalArgumentException(\"tokenSecretKey value is neither a valid file nor valid base64: \" + e.getMessage(), e); }","preventionTips":["Paste base64 keys as one line with no internal whitespace","Beware YAML/properties line-continuation mangling long values","Test-decode the config value in CI before deploying"],"tags":["authentication","crypto","base64","configuration"],"backgroundTag":"invalid-base64-key","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}