apache/hadoop · critical · AccessControlException

Client already attempted negotiation

Error message

Client already attempted negotiation

What it means

In processSaslMessage's NEGOTIATE case, a second NEGOTIATE on a connection where the server already sent its advertise list (sentNegotiate true) is rejected with AccessControlException("Client already attempted negotiation") — the source even carries a FIXME noting SaslException might be more apt. The client restarted a handshake the server already answered.

Source

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

     * @param saslMessage received SASL message
     * @return the sasl response to send back to client
     * @throws SaslException if authentication or generating response fails, 
     *                       or SASL protocol mixup
     * @throws IOException if a SaslServer cannot be created
     * @throws AccessControlException if the requested authentication type 
     *         is not supported or trying to re-attempt negotiation.
     * @throws InterruptedException
     */
    private RpcSaslProto processSaslMessage(RpcSaslProto saslMessage)
        throws SaslException, IOException, AccessControlException,
        InterruptedException {
      final RpcSaslProto saslResponse;
      final SaslState state = saslMessage.getState(); // required      
      switch (state) {
        case NEGOTIATE: {
          if (sentNegotiate) {
            // FIXME shouldn't this be SaslException?
            throw new AccessControlException(
                "Client already attempted negotiation");
          }
          saslResponse = buildSaslNegotiateResponse();
          // simple-only server negotiate response is success which client
          // interprets as switch to simple
          if (saslResponse.getState() == SaslState.SUCCESS) {
            switchToSimple();
          }
          break;
        }
        case INITIATE: {
          if (saslMessage.getAuthsCount() != 1) {
            throw new SaslException("Client mechanism is malformed");
          }
          // verify the client requested an advertised authType
          SaslAuth clientSaslAuth = saslMessage.getAuths(0);
          if (!negotiateResponse.getAuthsList().contains(clientSaslAuth)) {
            if (sentNegotiate) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Send NEGOTIATE exactly once per connection and handle the server's response instead of resending.
  2. If the negotiate response was lost, close the connection and start a new one — never renegotiate in place.
  3. Use standard Hadoop RPC client stacks, which sequence the handshake correctly.

Example fix

// before
if (!negotiateResponseReceived && elapsed > timeout) {
  sendNegotiate(); // duplicate NEGOTIATE -> AccessControlException
}
// after
if (!negotiateResponseReceived && elapsed > timeout) {
  conn.close();
  conn = newConnection();
  sendNegotiateOnce(conn);
}
Defensive patterns

Strategy: try-catch

Try / catch

Catch AccessControlException from the SASL exchange with 'already attempted' semantics as fatal for that connection: close it, open a new one, and send NEGOTIATE exactly once there.

Prevention

When it happens

Trigger: Client sends NEGOTIATE, then sends NEGOTIATE again on the same connection: retry-on-timeout logic that ignores the first response, duplicated frames from a proxy, or a custom client that loops the handshake.

Common situations: Custom clients resending negotiate on a timeout; transparent proxies duplicating requests; client/server version skew in SASL sequencing; replayed test fixtures.

Related errors


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