apache/hadoop · error · IOException

Wrong key length. Required ${meta.getBitLength()}, but got $

Error message

Wrong key length. Required ${meta.getBitLength()}, but got ${8 * material.length}

What it means

When rolling a new version, the supplied material must match the bit length stored in the key's existing Metadata: meta.getBitLength() == 8 * material.length. The provider enforces this so every version of a key stays interchangeable with earlier versions and with the recorded cipher metadata; the check runs before the version counter is incremented.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/JavaKeyStoreProvider.java:518

    } catch (KeyStoreException e) {
      throw new IOException("Can't store key " + versionName + " in " + this,
          e);
    }
    changed = true;
    return new KeyVersion(name, versionName, material);
  }

  @Override
  public KeyVersion rollNewVersion(String name,
                                    byte[] material) throws IOException {
    writeLock.lock();
    try {
      Metadata meta = getMetadata(name);
      if (meta == null) {
        throw new IOException("Key " + name + " not found");
      }
      if (meta.getBitLength() != 8 * material.length) {
        throw new IOException("Wrong key length. Required " +
            meta.getBitLength() + ", but got " + (8 * material.length));
      }
      int nextVersion = meta.addVersion();
      String versionName = buildVersionName(name, nextVersion);
      return innerSetKeyVersion(name, versionName, material, meta.getCipher());
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public void flush() throws IOException {
    Path newPath = constructNewPath(path);
    Path oldPath = constructOldPath(path);
    Path resetPath = path;
    writeLock.lock();
    try {
      if (!changed) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Read the required size from provider.getMetadata(name).getBitLength() and allocate bitLength/8 bytes
  2. Prefer the one-arg rollNewVersion(name), which generates material from the stored metadata via generateKey
  3. Centralize key-material generation in one helper that always sizes from Metadata

Example fix

// before
byte[] material = new byte[16]; // assumes 128-bit
provider.rollNewVersion(name, material);

// after
int bits = provider.getMetadata(name).getBitLength();
byte[] material = new byte[bits / Byte.SIZE];
new SecureRandom().nextBytes(material);
provider.rollNewVersion(name, material);
Defensive patterns

Strategy: validation

Validate before calling

KeyProvider.Metadata meta = provider.getMetadata(name);
if (meta == null) throw new IOException("key not found: " + name);
if (8 * material.length != meta.getBitLength()) {
  material = new byte[meta.getBitLength() / Byte.SIZE];
  new SecureRandom().nextBytes(material);
}
provider.rollNewVersion(name, material);

Try / catch

catch (IOException e) { if (String.valueOf(e.getMessage()).startsWith("Wrong key length")) { // resize material from getMetadata(name).getBitLength()/8 and retry } else { throw e; } }

Prevention

When it happens

Trigger: Generating 128-bit material for a key originally created with setBitLength(256); sizing material from a fresh Options object instead of the key's actual metadata; copying generation code from another key with a different size.

Common situations: Clients that hard-code 16-byte material; keys created years ago with non-default lengths; refactors that lost the metadata-driven sizing.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/a38e850f943e6aa0. Report an issue: GitHub.