apache/hadoop · error · IOException

Provided name '{}' has {} components instead of the expected

Error message

Provided name '{}' has {} components instead of the expected 3.

What it means

In the specialized encrypted data-transfer handshake, the SASL username must encode exactly three parts - encryption keyId, blockPoolId and Base64 nonce - separated by the single-space NAME_DELIMITER (' ', DataTransferSaslUtil.java:80). SaslDataTransferServer.getEncryptionKeyFromUserName splits on that delimiter and rejects any component count other than 3 before looking up the key.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocol/datatransfer/sasl/SaslDataTransferServer.java:286

        final char[] password = name != null ? passwordFunction.apply(name) : null;
        customizedCallbackHandler.handleCallbacks(unknownCallbacks, name, password);
      }
    }
  }

  /**
   * Given a secret manager and a username encoded for the encrypted handshake,
   * determine the encryption key.
   * 
   * @param userName containing the keyId, blockPoolId, and nonce.
   * @return secret encryption key.
   * @throws IOException
   */
  private byte[] getEncryptionKeyFromUserName(String userName)
      throws IOException {
    String[] nameComponents = userName.split(NAME_DELIMITER);
    if (nameComponents.length != 3) {
      throw new IOException("Provided name '" + userName + "' has " +
          nameComponents.length + " components instead of the expected 3.");
    }
    int keyId = Integer.parseInt(nameComponents[0]);
    String blockPoolId = nameComponents[1];
    byte[] nonce = Base64.decodeBase64(nameComponents[2]);
    return blockPoolTokenSecretManager.retrieveDataEncryptionKey(keyId,
        blockPoolId, nonce);
  }

  /**
   * Receives SASL negotiation for general-purpose handshake.
   *
   * @param peer connection peer
   * @param underlyingOut connection output stream
   * @param underlyingIn connection input stream
   * @return new pair of streams, wrapped after SASL negotiation
   * @throws IOException for any error
   */

View on GitHub (pinned to 2add963021)

Solutions

  1. Align client and DataNode Hadoop versions so the encoding matches
  2. If implementing the protocol manually, build the username exactly as keyId + " " + blockPoolId + " " + Base64(nonce)
  3. Treat occurrences as a misbehaving/corrupted peer: capture the exchange (pcap) and identify the client from DN logs

Example fix

// before (custom client): wrong delimiter
String userName = keyId + "|" + blockPoolId + "|" + b64Nonce;
// after
String userName = keyId + " " + blockPoolId + " " + b64Nonce;
Defensive patterns

Strategy: try-catch

Validate before calling

// If you implement the client side, self-check before sending
static String buildEncryptedHandshakeUserName(long keyId, String blockPoolId, byte[] nonce) {
  String userName = keyId + " " + blockPoolId + " "
      + org.apache.commons.codec.binary.Base64.encodeBase64String(nonce);
  assert userName.split(" ").length == 3 : "malformed SASL username";
  return userName;
}

Try / catch

Server side: catch (IOException e) inside getEncryptionKeyFromUserName / SASL negotiation; on the 'components instead of the expected 3' message, drop and log the peer - the handshake cannot recover. Client side: verify your encoding before connecting.

Prevention

When it happens

Trigger: A client composing the encrypted-handshake username incorrectly (wrong delimiter, missing nonce, extra spaces that change the split count); version skew changing the encoding; corrupted input making the split yield a different number of parts.

Common situations: Homegrown/custom clients implementing the data-encryption-key handshake themselves; fuzzed or corrupted streams; peers running divergent Hadoop versions with incompatible username encodings.

Related errors


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