apache/hadoop · critical · AccessControlException

Can't retrieve username from tokenIdentifier.

Error message

Can't retrieve username from tokenIdentifier.

What it means

On a TOKEN-authenticated connection, getAuthorizedUgi resolves the SASL identity through SaslRpcServer.getIdentifier to a TokenIdentifier and asks it for its UserGroupInformation; if tokenId.getUser() returns null, authorization fails with AccessControlException("Can't retrieve username from tokenIdentifier."). The token parsed, but its identifier could not name an owning user — a server-side auth failure that kills the connection.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java:2235

    
    /* Decrement the outstanding RPC count */
    private void decRpcCount() {
      rpcCount.decrementAndGet();
    }
    
    /* Increment the outstanding RPC count */
    private void incRpcCount() {
      rpcCount.incrementAndGet();
    }
    
    private UserGroupInformation getAuthorizedUgi(String authorizedId)
        throws InvalidToken, AccessControlException {
      if (authMethod == AuthMethod.TOKEN) {
        TokenIdentifier tokenId = SaslRpcServer.getIdentifier(authorizedId,
            secretManager);
        UserGroupInformation ugi = tokenId.getUser();
        if (ugi == null) {
          throw new AccessControlException(
              "Can't retrieve username from tokenIdentifier.");
        }
        ugi.addTokenIdentifier(tokenId);
        return ugi;
      } else {
        return UserGroupInformation.createRemoteUser(authorizedId, authMethod);
      }
    }

    private void saslReadAndProcess(RpcWritable.Buffer buffer) throws
        RpcServerException, IOException, InterruptedException {
      final RpcSaslProto saslMessage =
          getMessage(RpcSaslProto.getDefaultInstance(), buffer);
      switch (saslMessage.getState()) {
        case WRAP: {
          if (!saslContextEstablished || !useWrap) {
            throw new FatalRpcServerException(
                RpcErrorCodeProto.FATAL_INVALID_RPC_HEADER,

View on GitHub (pinned to 2add963021)

Solutions

  1. If you own the TokenIdentifier class, implement getUser() to return the owning UserGroupInformation — never null.
  2. Verify the token's kind maps to the intended identifier class in SaslRpcServer's token identifier registry so it decodes with full owner info.
  3. As a client, obtain a fresh delegation token from the target service — the old one decodes to an identifier without a user.

Example fix

// before
public class MyTokenIdentifier extends AbstractDelegationTokenIdentifier {
  @Override
  public UserGroupInformation getUser() {
    return null; // triggers AccessControlException on the server
  }
}
// after
@Override
public UserGroupInformation getUser() {
  return UserGroupInformation.createRemoteUser(getOwner().toString());
}
Defensive patterns

Strategy: try-catch

Try / catch

Catch AccessControlException on the RPC/connection layer, treat it as a non-retryable authentication failure, and re-authenticate: fetch a fresh delegation token from the target service (or re-login for Kerberos) before reconnecting.

Prevention

When it happens

Trigger: A delegation token whose TokenIdentifier.getUser() returns null: custom TokenIdentifier implementations that never return a user, token kinds mapped to an identifier class without owner information, or tokens minted by a mismatched/older service version so the identifier decodes without an owner.

Common situations: Custom authentication plugins introducing new token kinds; tokens carried across service versions; proxy-user setups where the identifier lost the owner field; WebHDFS/HTTP flows surfacing this as a 401/connection failure.

Related errors


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