apache/beam · error · java.lang.RuntimeException

The private key is encrypted but no private key key…

Error message

The private key is encrypted but no private key key passphrase has been provided.

What it means

KeyPairUtils.preparePrivateKey inspects the PEM header to detect encryption. If the key is encrypted (ENCRYPT state) but privateKeyPassphrase is null or empty, it throws this RuntimeException, because it cannot decrypt the key for Snowflake key-pair authentication.

Solutions

  1. Provide the passphrase via Snowflake key-pair config (privateKeyPassphrase / sfPrivateKeyPassphrase property).
  2. Regenerate the key unencrypted if the passphrase is not needed: openssl pkcs8 -topk8 -nocrypt ... or `openssl genpkey -algorithm RSA` with -aes... omitted / use `openssl rsa -in key.pem -out key-unenc.pem`.
  3. Check that the passphrase env var/secret is actually populated at runtime (not empty string).

Example fix

// before
KeyPairUtils.preparePrivateKey(privateKeyPem, null);

// after
KeyPairUtils.preparePrivateKey(privateKeyPem, System.getenv("SNOWFLAKE_KEY_PASSPHRASE"));
Defensive patterns

Strategy: validation

Validate before calling

boolean encrypted = pem.contains("BEGIN ENCRYPTED PRIVATE KEY");
if (encrypted && (passphrase == null || passphrase.isEmpty())) {
  throw new IllegalStateException("Passphrase required for encrypted private key");
}

Try / catch

try {
  KeyPair kp = KeyPairUtils.preparePrivateKey(pem, passphrase);
} catch (RuntimeException e) {
  if (e.getMessage().contains("passphrase")) {
    // surface config error: prompt/require SNOWFLAKE_KEY_PASSPHRASE
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling preparePrivateKey with an encrypted PKCS#8 PEM ("ENCRYPTED PRIVATE KEY" header, e.g. produced by newer OpenSSL) and passing null/"" as passphrase.

Common situations: Generating a key with openssl genpkey (encrypted by default) and forgetting to pass the passphrase in the Snowflake config; passphrase stored in a separate env var that is unset; key regenerated encrypted after previously being unencrypted.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/23beebbfdae5c5db. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/snowflake/src/main/java/org/apache/beam/sdk/io/snowflake/KeyPairUtils.java:58

public class KeyPairUtils {
  private static final String ENCRYPTED_PRIVATE_KEY = "ENCRYPTED PRIVATE KEY";
  private static final String UNENCRYPTED_PRIVATE_KEY = "PRIVATE KEY";

  private enum KeyEncryptionState {
    ENCRYPT,
    UNENCRYPTED,
    UNKNOWN
  }

  @SuppressFBWarnings("DCN_NULLPOINTER_EXCEPTION")
  public static PrivateKey preparePrivateKey(String privateKey, String privateKeyPassphrase) {
    try {
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      KeyEncryptionState encryptionState = guessKeyEncryptionState(privateKey);
      if (encryptionState == KeyEncryptionState.ENCRYPT
          && Strings.isNullOrEmpty(privateKeyPassphrase)) {
        throw new RuntimeException(
            "The private key is encrypted but no private key key passphrase has been provided.");
      }

      if (encryptionState == KeyEncryptionState.UNENCRYPTED
          && !Strings.isNullOrEmpty(privateKeyPassphrase)) {
        throw new RuntimeException(
            "The private key is unencrypted but private key key passphrase has been provided.");
      }

      byte[] decoded;

      if (encryptionState == KeyEncryptionState.UNKNOWN) {
        decoded = Base64.decode(privateKey);
      } else {
        PemReader pr = new PemReader(new StringReader(privateKey));
        PemObject pemObject = pr.readPemObject();
        decoded = pemObject.getContent();
        pr.close();

View on GitHub (pinned to 12126d8942)