apache/pulsar · error · IOException
Illegal base64 character or Key file ${keyConfUrl} doesn't e
Error message
Illegal base64 character or Key file ${keyConfUrl} doesn't exist What it means
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.
Source
Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/utils/AuthTokenUtils.java:131
if (keyConfUrl.startsWith("file:")) {
keyConfUrl = keyConfUrl.trim();
}
return IOUtils.toByteArray(URL.createURL(keyConfUrl));
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e);
}
} else if (Files.exists(Paths.get(keyConfUrl))) {
// Assume the key content was passed in a valid file path
return Files.readAllBytes(Paths.get(keyConfUrl));
} else if (Base64.isBase64(keyConfUrl.getBytes())) {
// Assume the key content was passed in base64
try {
return Decoders.BASE64.decode(keyConfUrl);
} catch (DecodingException e) {
String msg = "Illegal base64 character or Key file " + keyConfUrl + " doesn't exist";
throw new IOException(msg, e);
}
} else {
String msg = "Secret/Public Key file " + keyConfUrl + " doesn't exist";
throw new IllegalArgumentException(msg);
}
}
}
View on GitHub (pinned to 820761864e)
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.
Example fix
// before
String keyConfUrl = "MIIBIjANBgkq...\n more=="; // embedded whitespace/newlines
// after
String keyConfUrl = key.replace("\n", "").replace(" ", "").trim(); // single clean base64 line Defensive patterns
Strategy: validation
Validate before calling
String clean = value.replaceAll("\\s", "");
if (!clean.matches("[A-Za-z0-9+/]*={0,2}")) throw new IllegalArgumentException("not clean base64");
java.util.Base64.getDecoder().decode(clean); // strict round-trip check Type guard
boolean isCleanBase64(String s) { return s != null && s.replaceAll("\\s", "").matches("[A-Za-z0-9+/]+={0,2}"); } Try / catch
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); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- The ${alg.name()} algorithm does not support Key Pairs.
- Invalid broker configuration. Authentication must be enabled
- No athenz domain name specified
- Invalid allowed offset for athenz role token verification sp
- Allowed offset for athenz role token verification must not b
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/7ef6aeb128db54c2.
Report an issue: GitHub.