apache/beam · error · java.lang.RuntimeException
Can't read parse private key
Error message
Can't read parse private key
What it means
KeyPairUtils.guessKeyEncryptionState reads a private key file and, if any IOException occurs while parsing the key's encryption state, wraps it in an uninformative RuntimeException('Can't read parse private key'). It is thrown only in the catch block after attempting to read the file contents, so it signals the key file could not be read or the input stream failed mid-parse.
Solutions
- Verify the private key file exists and is readable at the exact path on the machine executing the transform (Beam workers may differ from your local machine).
- Stage the key file with Beam's FileSystems/withBeamPipelineOptions (e.g. copy to a GCS path and use snowflake's keyFile staging) instead of relying on a local path.
- Convert the PKCS8 key to a plain unencrypted file (openssl pkcs8 -topk8 -nocrypt) if you don't need passphrase encryption, avoiding the encrypted-key parse path.
- Check file permissions (chmod 400/600) and that the path is absolute.
Example fix
// before
.withPrivateKey("/home/me/wrong-name.p8")
// after
.withPrivateKey("/etc/beam/keys/rsa_key.p8") // absolute, existing, readable path Defensive patterns
Strategy: validation
Validate before calling
java.nio.file.Path p = java.nio.file.Paths.get(keyPath);
if (!java.nio.file.Files.isRegularFile(p) || !java.nio.file.Files.isReadable(p)) {
throw new IllegalStateException("Private key file missing or unreadable: " + p);
} Prevention
- Use absolute paths for key files.
- Stage key files with the pipeline (worker images differ from local machines).
- Check readability with Files.isReadable before building the pipeline.
- Prefer unencrypted PKCS8 keys when passphrase handling isn't needed.
When it happens
Trigger: Calling SnowflakeIO with a private key path/file whose underlying IOException occurs inside guessKeyEncryptionState (e.g. unreadable file, invalid path, stream closed) while the transform determines whether the key is ENCRYPTED_PRIVATE_KEY or UNENCRYPTED_PRIVATE_KEY.
Common situations: Private key file deleted or moved after config was written; wrong path or relative path resolved against a different working directory on a Beam worker; file permissions deny read on the runner node; key file is a directory or symlink to nothing.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Can't read private key from provided path
- Can't create private key: + e.getMessage()
- Config file + configFile + does not exist
- Could not access keytab file. Make sure that the…
- Could not parse the provided Transform Service config file…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/98bed4f36dc2b09d.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/snowflake/src/main/java/org/apache/beam/sdk/io/snowflake/KeyPairUtils.java:138
if (pemObject == null) {
// If it is not a PEM file then it is not possible to determine the encryption state
return KeyEncryptionState.UNKNOWN;
}
if (ENCRYPTED_PRIVATE_KEY.equals(pemObject.getType())) {
return KeyEncryptionState.ENCRYPT;
} else if (UNENCRYPTED_PRIVATE_KEY.equals(pemObject.getType())) {
return KeyEncryptionState.UNENCRYPTED;
} else {
throw new RuntimeException(
"Invalid type of PEM file: "
+ pemObject.getType()
+ ". Supported types: "
+ ENCRYPTED_PRIVATE_KEY
+ ", "
+ UNENCRYPTED_PRIVATE_KEY);
}
} catch (IOException e) {
throw new RuntimeException("Can't read parse private key");
}
}
public static String readPrivateKeyFile(String privateKeyPath) {
try {
byte[] keyBytes = Files.readAllBytes(Paths.get(privateKeyPath));
return new String(keyBytes, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException("Can't read private key from provided path");
}
}
}
View on GitHub (pinned to 12126d8942)