apache/beam · error · java.lang.RuntimeException

Can't create private key: + e.getMessage()

Error message

Can't create private key: + e.getMessage()

What it means

preparePrivateKey wraps InvalidKeySpecException, IOException, IllegalArgumentException, NullPointerException, InvalidKeyException, and DecoderException in a RuntimeException with this message. It means the PEM content could not be parsed, decoded (Base64/hex), or converted into an RSA PrivateKey.

Solutions

  1. Verify you are passing the PEM file's CONTENTS (including -----BEGIN/END----- lines), not a file path.
  2. Check the PEM is intact: valid Base64 body and matching BEGIN/END headers; re-copy from source with correct newlines.
  3. Inspect the cause's message (getCause()) to identify which parsing step failed.
  4. Regenerate or re-export the key (openssl pkcs8 -topk8 ...) if the file itself is truncated/corrupt.

Example fix

// before
String key = "/etc/snowflake/rsa_key.p8";                 // wrong: path
KeyPairUtils.preparePrivateKey(key, passphrase);
// after
String key = Files.readString(Path.of("/etc/snowflake/rsa_key.p8"));
KeyPairUtils.preparePrivateKey(key, passphrase);
Defensive patterns

Strategy: validation

Validate before calling

if (pem == null || !pem.contains("-----BEGIN") || !pem.contains("PRIVATE KEY-----")) {
  throw new IllegalArgumentException("Value must be PEM private key contents, not a path or truncated text");
}

Try / catch

try {
  PrivateKey pk = KeyPairUtils.preparePrivateKey(pem, passphrase);
} catch (RuntimeException e) {
  if (e.getMessage().startsWith("Can't create private key")) {
    logger.error("PEM parse failed; check contents/newlines. Cause: {}", e.getCause());
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing malformed PEM text (missing header/footer), non-Base64 body, an empty/whitespace string, a truncated key, or a value read from a file/path instead of the key contents itself.

Common situations: Storing the key in a property file where newlines are mangled (\\n escaping issues); accidentally passing a file path rather than the file's contents; env var stripping newlines; copying the key with extra whitespace or missing footer.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

        PKCS8EncodedKeySpec encodedKeySpec =
            pkInfo.getKeySpec(pbeKeyFactory.generateSecret(keySpec));
        return keyFactory.generatePrivate(encodedKeySpec);
      }
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(
          "Private key encryption algorithm not supported. This may mean that the private key was generated by OpenSSL 1.1.1g or newer "
              + "which uses an encryption algorithm by default which has compatibility issues in some JVM environments. "
              + "For details, see: "
              + "https://community.snowflake.com/s/article/Private-key-provided-is-invalid-or-not-supported-rsa-key-p8--data-isn-t-an-object-ID"
              + " "
              + e.getMessage());
    } catch (InvalidKeySpecException
        | IOException
        | IllegalArgumentException
        | NullPointerException
        | InvalidKeyException
        | DecoderException e) {
      throw new RuntimeException("Can't create private key: " + e.getMessage(), e);
    }
  }

  /**
   * Tries to determine whether the private key is encrypted or not based on the file headers.
   *
   * <p>If this is not possible (e.g. there are no headers), returns {@link
   * KeyEncryptionState#UNKNOWN}
   */
  private static KeyEncryptionState guessKeyEncryptionState(String privateKey) {
    PemReader pr = new PemReader(new StringReader(privateKey));
    try {
      PemObject pemObject = pr.readPemObject();
      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())) {

View on GitHub (pinned to 12126d8942)