apache/iceberg · error · UnsupportedOperationException

Key generation is not supported in this KmsClient

Error message

Key generation is not supported in this KmsClient

What it means

KmsClient is the pluggable interface Iceberg uses to talk to a key management service. generateKey has a default implementation that throws UnsupportedOperationException because most KMS integrations only wrap/unwrap customer-managed keys and cannot create new data keys. Multi-key (hybrid) encryption requires a KmsClient that implements key generation (e.g., AWS KMS with GenerateDataKey).

Source

Thrown at api/src/main/java/org/apache/iceberg/encryption/KmsClient.java:64

   * @return true if KMS server supports key generation and KmsClient implementation is interested
   *     to leverage this capability. Otherwise, return false - Iceberg will then generate secret
   *     keys locally (using the SecureRandom mechanism) and call {@link #wrapKey(ByteBuffer,
   *     String)} to wrap them in KMS.
   */
  default boolean supportsKeyGeneration() {
    return false;
  }

  /**
   * Generate a new secret key in the KMS server, and wrap it using a wrapping/master key which is
   * stored in KMS and referenced by an ID. This method will be called only if supportsKeyGeneration
   * returns true.
   *
   * @param wrappingKeyId a key ID that represents a wrapping key stored in KMS
   * @return key in two forms: raw, and wrapped with the given wrappingKeyId
   */
  default KeyGenerationResult generateKey(String wrappingKeyId) {
    throw new UnsupportedOperationException("Key generation is not supported in this KmsClient");
  }

  /**
   * Unwrap a secret key, using a wrapping/master key which is stored in KMS and referenced by an
   * ID.
   *
   * @param wrappedKey wrapped key material (encrypted key and optional KMS metadata, returned by
   *     the wrapKey method)
   * @param wrappingKeyId a key ID that represents a wrapping key stored in KMS
   * @return raw key bytes
   */
  ByteBuffer unwrapKey(String wrappedKey, String wrappingKeyId);

  /**
   * Initialize the KMS client with given properties
   *
   * @param properties kms client properties
   */

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Configure a KmsClient implementation that supports key generation and returns true for supportsKeyGeneration() (e.g., the AWS KMS client based on GenerateDataKey).
  2. If multi-key encryption is not required, use single-key encryption with kms.wrapKey so generateKey is never invoked.
  3. Implement generateKey in your custom KmsClient, producing a raw key plus a key wrapped with the given wrappingKeyId.
  4. Update your encryption configuration to avoid key splitting (reduce key length/number of keys so the basic path is used).
  5. Guard feature-detection: check supportsKeyGeneration() before enabling multi-key encryption.

Example fix

// before
catalog.properties: io.manifest.cache ... 
EncryptedOutputFile out = encryptedIO.newEncryptingOutputFile(...); // uses multi-key path -> generateKey -> throws
// after
public class AwsKmsClient implements KmsClient {
  @Override
  public boolean supportsKeyGeneration() {
    return true;
  }

  @Override
  public KeyGenerationResult generateKey(String wrappingKeyId) {
    GenerateDataKeyResult r = kms.generateDataKey(...);
    return new KeyGenerationResult(ByteBuffer.wrap(r.getPlaintext()), ByteBuffer.wrap(r.getCiphertextBlob()));
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean closeable = encryptionManager instanceof Closeable;
if (!closeable) { io.close(); return; }

Type guard

boolean safelyCloseable(Object em) {
  return em instanceof Closeable;
}

Try / catch

try {
  io.close();
} catch (UncheckedIOException e) {
  if ("Failed to close encryption manager".equals(e.getMessage())) {
    LOG.warn("encryption manager cleanup failed", e.getCause());
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Running encryption with a key-splitting/multi-key enclosure that calls kms.generateKey(wrappingKeyId) while the configured KmsClient only implements wrap/unwrap (the default method is hit).

Common situations: Configuring table encryption with write.metadata.metrics / encryption properties using a basic KMS plugin that lacks key-generation; using a mock or custom KmsClient in tests; older catalog KMS adapters that predate key generation support.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/eba54e872062e216. Report an issue: GitHub.