{"record":{"id":"c702b212df0a1326","repo":"apache/hadoop","slug":"invalid-spnego-sequence-status-code","errorCode":null,"errorMessage":"Invalid SPNEGO sequence, status code: {}","messagePattern":"Invalid SPNEGO sequence, status code: (.+?)","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/KerberosAuthenticator.java","lineNumber":402,"sourceCode":"  /*\n  * Retrieves the Kerberos token returned by the server.\n  */\n  private byte[] readToken(HttpURLConnection conn)\n      throws IOException, AuthenticationException {\n    int status = conn.getResponseCode();\n    if (status == HttpURLConnection.HTTP_OK || status == HttpURLConnection.HTTP_UNAUTHORIZED) {\n      String authHeader = conn.getHeaderField(WWW_AUTHENTICATE);\n      if (authHeader == null) {\n        authHeader = conn.getHeaderField(WWW_AUTHENTICATE.toLowerCase());\n      }\n      if (authHeader == null || !authHeader.trim().startsWith(NEGOTIATE)) {\n        throw new AuthenticationException(\"Invalid SPNEGO sequence, '\" + WWW_AUTHENTICATE +\n                                          \"' header incorrect: \" + authHeader);\n      }\n      String negotiation = authHeader.trim().substring((NEGOTIATE + \" \").length()).trim();\n      return base64.decode(negotiation);\n    }\n    throw new AuthenticationException(\"Invalid SPNEGO sequence, status code: \" + status);\n  }\n\n}\n","sourceCodeStart":384,"sourceCodeEnd":406,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/client/KerberosAuthenticator.java#L384-L406","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","For 500s, check the server's hadoop-auth/kerberos configuration: keytab path, HTTP/<host>@REALM principal, realm/krb5.conf validity.","If an LB sits in front, health-check and bypass it to confirm the backend answers 401+Negotiate directly.","Point the client straight at the final (https) endpoint so no redirect occurs mid-handshake."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"HttpURLConnection probe = (HttpURLConnection) url.openConnection();\nint rc = probe.getResponseCode();\nif (rc != HttpURLConnection.HTTP_OK && rc != HttpURLConnection.HTTP_UNAUTHORIZED) {\n  throw new IOException(\"Non-SPNEGO response \" + rc + \" from \" + url + \" — fix redirect/LB/server\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  new KerberosAuthenticator().authenticate(url, token);\n} catch (AuthenticationException e) {\n  java.util.regex.Matcher m = java.util.regex.Pattern.compile(\"status code: (\\\\d+)\").matcher(e.getMessage());\n  if (m.find()) { int code = Integer.parseInt(m.group(1)); handleNonSpnegoStatus(code, url); }\n  throw e;\n}","preventionTips":["Target the final https endpoint directly to avoid 302s mid-handshake.","Monitor backend health behind LBs; SPNEGO cannot pass through 5xx error pages.","Fix server-side 500s (keytab/principal) before debugging the client."],"tags":["kerberos","spnego","http-status","redirect","hadoop-auth","authentication"],"backgroundTag":"spnego-handshake-failed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}