{"record":{"id":"f8258f2e8a58bd5a","repo":"apache/hadoop","slug":"currentkey-hasn-t-been-initialized","errorCode":null,"errorMessage":"currentKey hasn't been initialized.","messagePattern":"currentKey hasn't been initialized\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/security/token/block/BlockTokenSecretManager.java","lineNumber":488,"sourceCode":"  public BlockTokenIdentifier createIdentifier() {\n    return new BlockTokenIdentifier();\n  }\n\n  /**\n   * Create a new password/secret for the given block token identifier.\n   *\n   * @param identifier\n   *          the block token identifier\n   * @return token password/secret\n   */\n  @Override\n  protected byte[] createPassword(BlockTokenIdentifier identifier) {\n    BlockKey key = null;\n    synchronized (this) {\n      key = currentKey;\n    }\n    if (key == null) {\n      throw new IllegalStateException(\"currentKey hasn't been initialized.\");\n    }\n    identifier.setExpiryDate(timer.now() + tokenLifetime);\n    identifier.setKeyId(key.getKeyId());\n    if (LOG.isDebugEnabled()) {\n      LOG.debug(\"Generating block token for \" + identifier);\n    }\n    return createPassword(identifier.getBytes(), key.getKey());\n  }\n\n  /**\n   * Look up the token password/secret for the given block token identifier.\n   *\n   * @param identifier\n   *          the block token identifier to look up\n   * @return token password/secret as byte[]\n   * @throws InvalidToken\n   */\n  @Override","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/security/token/block/BlockTokenSecretManager.java#L470-L506","documentation":"BlockTokenSecretManager.createPassword throws IllegalStateException when a block token is requested but currentKey is null, i.e., the key-rolling machinery never produced an initial key. The secret manager generates keys on construction (generateKeys) or receives them via setKeys() when the NameNode loads fsimage; if neither happened, no password can be computed. It is a lifecycle bug: token generation was attempted before initialization, not a transient condition.","triggerScenarios":"generateToken/createPassword is called on a BlockTokenSecretManager whose currentKey was never set — e.g., before loadSecretManager state from fsimage was applied, before the first rollKeysTimer tick that calls generateKeys, or on a manager constructed for read-only verification (where setKeys was skipped) that is mistakenly used to mint tokens.","commonSituations":"Custom tooling/tests constructing BlockTokenSecretManager directly and calling generateToken without generateKeys()/setKeys(); NN code path issuing tokens (addBlock, DN handshake) racing ahead of image load; after an upgrade where setKeys ordering changed; using a secret manager intended only for password verification to also create tokens.","solutions":["Ensure the manager is initialized before any token minting: for a fresh cluster call generateKeys() (or setKeys(...) with keys from fsimage) prior to generateToken.","In NameNode context, confirm the active state (fsimage load) completed before serving RPCs that mint block tokens — check startup ordering in logs.","For read-only consumers, use a manager configured with keys loaded from the same source instead of an uninitialized one.","Add a startup assertion / health check getCurrentKey() != null to fail fast at boot rather than at first token request."],"exampleFix":"// before\nBlockTokenSecretManager sm = new BlockTokenSecretManager(keyUpdateInterval, tokenLifetime, 0, \"BP-1\", false);\nToken<BlockTokenIdentifier> t = sm.generateToken(...); // IllegalStateException\n\n// after\nsm = new BlockTokenSecretManager(keyUpdateInterval, tokenLifetime, 0, \"BP-1\", true);\nsm.setKeys(new BlockTokenSecretManager.Keys(...)); // or let ctor's generateKeys run\nassert sm.getCurrentKey() != null;\nToken<BlockTokenIdentifier> t = sm.generateToken(...);","handlingStrategy":"validation","validationCode":"if (blockTokenSecretManager.getCurrentKey() == null) {\n  // keys not loaded yet: initialize (generateKeys/setKeys) before minting tokens\n  blockTokenSecretManager.setKeys(loadKeysFromImageOrGenerate());\n}","typeGuard":null,"tryCatchPattern":"try {\n  token = sm.generateToken(dn, block, modes);\n} catch (IllegalStateException e) {\n  if (\"currentKey hasn't been initialized.\".equals(e.getMessage())) {\n    // lifecycle bug: initialize keys first, fail loudly rather than loop\n    sm.setKeys(loadKeys());\n  } else { throw e; }\n}","preventionTips":["Initialize keys (generateKeys or setKeys from fsimage) before the NN serves token-minting RPCs.","Add a boot-time assertion getCurrentKey() != null to fail at startup, not at first request.","Never use a verification-only BlockTokenSecretManager to mint tokens."],"tags":["hdfs","block-token","security","initialization","lifecycle"],"backgroundTag":"component-not-initialized","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}