{"record":{"id":"b1d4641ce86c173a","repo":"apache/hadoop","slug":"wrong-key-length-required-bitlength-but-got","errorCode":null,"errorMessage":"Wrong key length. Required ${bitLength}, but got ${actualBitLength}","messagePattern":"Wrong key length\\. Required (.+?), but got (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/UserProvider.java","lineNumber":90,"sourceCode":"    }\n    byte[] serialized = credentials.getSecretKey(new Text(name));\n    if (serialized == null) {\n      return null;\n    }\n    Metadata result = new Metadata(serialized);\n    cache.put(name, result);\n    return result;\n  }\n\n  @Override\n  public synchronized KeyVersion createKey(String name, byte[] material,\n                               Options options) throws IOException {\n    Text nameT = new Text(name);\n    if (credentials.getSecretKey(nameT) != null) {\n      throw new IOException(\"Key \" + name + \" already exists in \" + this);\n    }\n    if (options.getBitLength() != 8 * material.length) {\n      throw new IOException(\"Wrong key length. Required \" +\n          options.getBitLength() + \", but got \" + (8 * material.length));\n    }\n    Metadata meta = new Metadata(options.getCipher(), options.getBitLength(),\n        options.getDescription(), options.getAttributes(), new Date(), 1);\n    cache.put(name, meta);\n    String versionName = buildVersionName(name, 0);\n    credentials.addSecretKey(nameT, meta.serialize());\n    credentials.addSecretKey(new Text(versionName), material);\n    return new KeyVersion(name, versionName, material);\n  }\n\n  @Override\n  public synchronized void deleteKey(String name) throws IOException {\n    Metadata meta = getMetadata(name);\n    if (meta == null) {\n      throw new IOException(\"Key \" + name + \" does not exist in \" + this);\n    }\n    for(int v=0; v < meta.getVersions(); ++v) {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/UserProvider.java#L72-L108","documentation":"UserProvider.createKey enforces the same size invariant as the keystore provider: options.getBitLength() must equal 8 * material.length, so the bytes stored in the user's credential store always match the Metadata created for the key. The check runs before any credential entry is added, so a rejected call leaves no partial state.","triggerScenarios":"Options built with setBitLength(256) while passing a 16-byte array; 32 random bytes passed with default (128-bit) Options; generation code sized independently of the options object.","commonSituations":"Shared example code with hard-coded 16-byte material; upgrading key size without touching generation logic; tests using arbitrary strings as material.","solutions":["Allocate material as new byte[options.getBitLength() / 8] and fill with SecureRandom","Prefer generateKey(bitLength, cipher) or the one-arg createKey(name, options) overload","Validate material.length == options.getBitLength() / 8 before the call"],"exampleFix":"// before\nOptions opts = new Options(conf).setCipher(\"AES\").setBitLength(256);\nbyte[] material = new byte[16];\nprovider.createKey(name, material, opts);\n\n// after\nOptions opts = new Options(conf).setCipher(\"AES\").setBitLength(256);\nbyte[] material = KeyProvider.generateKey(opts.getBitLength(), \"AES\");\nprovider.createKey(name, material, opts);","handlingStrategy":"validation","validationCode":"if (material == null || 8 * material.length != options.getBitLength()) {\n  throw new IllegalArgumentException(\"material bits=\" + (material == null ? 0 : 8 * material.length) + \", required=\" + options.getBitLength());\n}\nprovider.createKey(name, material, options);","typeGuard":null,"tryCatchPattern":"catch (IOException e) { if (String.valueOf(e.getMessage()).startsWith(\"Wrong key length\")) { material = KeyProvider.generateKey(options.getBitLength(), options.getCipher()); provider.createKey(name, material, options); } else { throw e; } }","preventionTips":["Derive material size from options.getBitLength()/8","Use generateKey or createKey(name, options) overloads","Never hard-code 16-byte material in shared helpers"],"tags":["java","hadoop","key-provider","key-management","validation","user-provider"],"backgroundTag":"key-length-mismatch","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}