apache/hadoop · error · UnsupportedCallbackException

Unrecognized SASL client callback

Error message

Unrecognized SASL client callback 

What it means

SaslRpcClient.AuthenticatorCallbackHandler only implements NameCallback, PasswordCallback, RealmCallback and AuthorizeCallback. When the JVM's SASL framework hands it any other Callback type (e.g. RealmChoiceCallback from a DIGEST-MD5 exchange), it throws UnsupportedCallbackException with this message. It signals that the negotiated SASL mechanism expects more from the client than Hadoop's handler was built to provide.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SaslRpcClient.java:694

      for (Callback callback : callbacks) {
        if (callback instanceof RealmChoiceCallback) {
          continue;
        } else if (callback instanceof NameCallback) {
          nc = (NameCallback) callback;
        } else if (callback instanceof PasswordCallback) {
          pc = (PasswordCallback) callback;
        } else if (callback instanceof RealmCallback) {
          rc = (RealmCallback) callback;
        } else if (callback instanceof AuthorizeCallback) {
          final AuthorizeCallback ac = (AuthorizeCallback) callback;
          final String authId = ac.getAuthenticationID();
          final String authzId = ac.getAuthorizationID();
          ac.setAuthorized(authId.equals(authzId));
          if (ac.isAuthorized()) {
            ac.setAuthorizedID(authzId);
          }
        } else {
          throw new UnsupportedCallbackException(callback,
              "Unrecognized SASL client callback " + callback.getClass());
        }
      }
      if (nc != null) {
        if (LOG.isDebugEnabled())
          LOG.debug("SASL client callback: setting username: " + userName);
        nc.setName(userName);
      }
      if (pc != null) {
        if (LOG.isDebugEnabled())
          LOG.debug("SASL client callback: setting userPassword");
        pc.setPassword(userPassword);
      }
      if (rc != null) {
        if (LOG.isDebugEnabled())
          LOG.debug("SASL client callback: setting realm: "
              + rc.getDefaultText());
        rc.setText(rc.getDefaultText());

View on GitHub (pinned to 2add963021)

Solutions

  1. Note the callback class named in the message and identify the mechanism in use (GSSAPI = KERBEROS, DIGEST-MD5 = TOKEN, PLAIN = SIMPLE over SASL)
  2. Remove third-party SASL providers from the JVM security configuration so JDK defaults apply
  3. Make client and server run compatible Hadoop versions with the same hadoop.security.authentication setting
  4. If you control a custom SaslClientFactory, extend SaslRpcClient's callback handler to accept the missing callback type
Defensive patterns

Strategy: try-catch

Try / catch

try {
  proxy = RPC.getProtocolProxy(proto, addr, ticket, conf);
} catch (IOException e) {
  Throwable root = e;
  while (root.getCause() != null) root = root.getCause();
  if (root instanceof UnsupportedCallbackException) {
    // unsupported SASL callback: check mechanism/provider setup, do not retry blindly
    throw new SecurityException("SASL callback not supported: " + root.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Establishing an RPC connection where the negotiated mechanism emits a callback outside the four supported types: a DIGEST-MD5 (TOKEN auth) exchange where the JDK passes RealmChoiceCallback, or a custom/extra SASL mechanism registered in java.security that requests additional callbacks during Sasl.createSaslClient negotiation.

Common situations: Mismatched Hadoop client/server versions negotiating different mechanisms, a JVM with non-standard or third-party SASL providers, custom authentication plugins, or JDK upgrades that change which callbacks the SASL factories emit.

Related errors


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