apache/pulsar · error · IllegalArgumentException
Failed to read decryption key from ${keyUri}
Error message
Failed to read decryption key from ${keyUri} What it means
buildFileDecryptionPolicy reads the decryption key file named by keyUri with Files.readAllBytes and wraps any IOException into an IllegalArgumentException. It means the file:// key location was valid as a URI but the bytes could not be read — typically the file is missing, unreadable, or a directory.
Source
Thrown at pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/AbstractCmdConsume.java:211
}
res.put(f.name(), fieldValue);
}
return res;
}
/**
* Build a consumer-side decryption policy from a {@code file://} key URI, mirroring the v4
* {@code defaultCryptoKeyReader(uri)} semantics: the private key is loaded once and returned
* for any key name. (The producer's logical key name travels in the message metadata, so a
* name-keyed provider would not resolve it; the CLI's file-based flow has a single key.)
*/
protected static ConsumerEncryptionPolicy buildFileDecryptionPolicy(
String keyUri, ConsumerCryptoFailureAction failureAction) {
final byte[] keyBytes;
try {
keyBytes = Files.readAllBytes(fileUriToPath(keyUri));
} catch (IOException e) {
throw new IllegalArgumentException("Failed to read decryption key from " + keyUri, e);
}
PrivateKeyProvider provider = (keyName, metadata) ->
CompletableFuture.completedFuture(EncryptionKey.of(keyBytes));
return ConsumerEncryptionPolicy.builder()
.privateKeyProvider(provider)
.failureAction(failureAction)
.build();
}
@WebSocket
@CustomLog
public static class ConsumerSocket {
private static final String X_PULSAR_MESSAGE_ID = "messageId";
private final CountDownLatch closeLatch;
private Session session;
private CompletableFuture<Void> connected;
final BlockingQueue<String> incomingMessages;
View on GitHub (pinned to 820761864e)
Solutions
- Verify the resolved path exists and is a regular file (Files.isRegularFile) and is readable (Files.isReadable)
- Fix the file:// URI (absolute path, correct host-empty form file:///path)
- Check filesystem permissions/ownership for the user running pulsar-client, and that any volume mount is present
- If the key is provisioned at startup, add a readiness check or wait loop before launching the consumer
Example fix
// before --decryption-key file:///etc/pulsar/decrytion-key.pem // typo, file absent // after ls -l /etc/pulsar/decryption-key.pem # verify first --decryption-key file:///etc/pulsar/decryption-key.pem
Defensive patterns
Strategy: validation
Validate before calling
Path p = fileUriToPath(keyUri);
if (!Files.isRegularFile(p) || !Files.isReadable(p))
throw new IllegalArgumentException("Decryption key not readable: " + p); Try / catch
try {
ConsumerEncryptionPolicy pol = buildFileDecryptionPolicy(keyUri, action);
} catch (IllegalArgumentException e) {
Throwable cause = e.getCause();
if (cause instanceof NoSuchFileException) {
LOG.error("Key file missing: {}", ((NoSuchFileException) cause).getFile());
} else if (cause instanceof AccessDeniedException) {
LOG.error("Key file not readable by current user");
} else { throw e; }
} Prevention
- Verify the key file exists and is readable as the same user running pulsar-client before launch
- Use absolute paths in file:// URIs to avoid working-directory surprises
- In containers/K8s, ensure secret volumes are mounted and add a readiness check on the key path
- Check file permissions after provisioning scripts that create the key as root
When it happens
Trigger: Calling CmdConsume with a decryption key URI whose path does not exist, lacks read permission, is a directory, or whose device/path vanished (container mount not present, NFS down).
Common situations: Kubernetes/pod volume not mounted where the key was expected; typo in the key filename; file created by root but CLI runs as another user; relative path resolved against an unexpected working directory.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- The specified jar file does not exist
- The specified python file does not exist
- The specified go executable binary does not exist
- Schema file %s is not found. Relative path %s is resolved to
- This version of pulsar-client supports only file:// encrypti
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a87c248f98cdac6d.
Report an issue: GitHub.