apache/hadoop · error · AuthenticationException

Invalid SPNEGO sequence, status code: {}

Error message

Invalid SPNEGO sequence, status code: {}

What it means

The sibling guard in KerberosAuthenticator.readToken: SPNEGO only continues on HTTP 200 or 401 (the two statuses that can legally carry the Negotiate header). Any other status — 302 redirect, 500, 503, etc. — aborts the handshake with AuthenticationException('Invalid SPNEGO sequence, status code: N'). The status number in the message identifies which non-SPNEGO response intercepted the conversation.

Source

Thrown at hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/KerberosAuthenticator.java:402

  /*
  * Retrieves the Kerberos token returned by the server.
  */
  private byte[] readToken(HttpURLConnection conn)
      throws IOException, AuthenticationException {
    int status = conn.getResponseCode();
    if (status == HttpURLConnection.HTTP_OK || status == HttpURLConnection.HTTP_UNAUTHORIZED) {
      String authHeader = conn.getHeaderField(WWW_AUTHENTICATE);
      if (authHeader == null) {
        authHeader = conn.getHeaderField(WWW_AUTHENTICATE.toLowerCase());
      }
      if (authHeader == null || !authHeader.trim().startsWith(NEGOTIATE)) {
        throw new AuthenticationException("Invalid SPNEGO sequence, '" + WWW_AUTHENTICATE +
                                          "' header incorrect: " + authHeader);
      }
      String negotiation = authHeader.trim().substring((NEGOTIATE + " ").length()).trim();
      return base64.decode(negotiation);
    }
    throw new AuthenticationException("Invalid SPNEGO sequence, status code: " + status);
  }

}

View on GitHub (pinned to 2add963021)

Solutions

  1. Reproduce the exact status with curl -v --negotiate -u : <url> and treat the number as the real problem: 302 -> follow/eliminate redirect (use the https URL directly); 5xx -> read the service's logs.
  2. For 500s, check the server's hadoop-auth/kerberos configuration: keytab path, HTTP/<host>@REALM principal, realm/krb5.conf validity.
  3. If an LB sits in front, health-check and bypass it to confirm the backend answers 401+Negotiate directly.
  4. Point the client straight at the final (https) endpoint so no redirect occurs mid-handshake.
Defensive patterns

Strategy: try-catch

Validate before calling

HttpURLConnection probe = (HttpURLConnection) url.openConnection();
int rc = probe.getResponseCode();
if (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_UNAUTHORIZED) {
  throw new IOException("Non-SPNEGO response " + rc + " from " + url + " — fix redirect/LB/server");
}

Try / catch

try {
  new KerberosAuthenticator().authenticate(url, token);
} catch (AuthenticationException e) {
  java.util.regex.Matcher m = java.util.regex.Pattern.compile("status code: (\\d+)").matcher(e.getMessage());
  if (m.find()) { int code = Integer.parseInt(m.group(1)); handleNonSpnegoStatus(code, url); }
  throw e;
}

Prevention

When it happens

Trigger: Server redirects http->https or to a login page (302) before the Negotiate exchange; gateway/LB returns 502/503 because the backend is down; authentication filter throws 500 (bad Kerberos keytab/secret config on the server); proxies intercepting with 407 or custom error codes.

Common situations: Enforcing-HTTPS front ends that 302 plain-HTTP SPNEGO clients instead of answering with a challenge; NameNode/WebHDFS down for maintenance behind an LB; server-side misconfiguration (missing keytab, wrong principal) causing 500s during authentication; captive portals/transparent proxies injecting 3xx.

Related errors


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