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
- Send NEGOTIATE exactly once per connection and handle the server's response instead of resending.
- If the negotiate response was lost, close the connection and start a new one — never renegotiate in place.
- 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
- Send NEGOTIATE once per connection and always consume the server's response before acting.
- On a lost/hung handshake, replace the connection rather than resending on it.
- Beware of proxies or replay logic that can duplicate SASL frames.
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
- Can't retrieve username from tokenIdentifier.
- FATAL_INVALID_RPC_HEADER
- Client mechanism is malformed
- ${method} authentication is not enabled. Available:${enable
- Server asks us to fall back to SIMPLE auth, but this client
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/921b664bd3543551.
Report an issue: GitHub.