{"record":{"id":"df499d76e2c8ade9","repo":"apache/hadoop","slug":"login-must-be-done-first","errorCode":null,"errorMessage":"login must be done first","messagePattern":"login must be done first","errorType":"exception","errorClass":"KerberosAuthException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java","lineNumber":1328,"sourceCode":"   * The Subject field of this UserGroupInformation object is updated to have\n   * the new credentials.\n   * @throws IOException raised on errors performing I/O.\n   * @throws KerberosAuthException on a failure\n   */\n  @InterfaceAudience.Public\n  @InterfaceStability.Evolving\n  public void reloginFromTicketCache() throws IOException {\n    reloginFromTicketCache(false);\n  }\n\n  private void reloginFromTicketCache(boolean ignoreLastLoginTime)\n      throws IOException {\n    if (!shouldRelogin() || !isFromTicket()) {\n      return;\n    }\n    HadoopLoginContext login = getLogin();\n    if (login == null) {\n      throw new KerberosAuthException(MUST_FIRST_LOGIN);\n    }\n    relogin(login, ignoreLastLoginTime);\n  }\n\n  private void relogin(HadoopLoginContext login, boolean ignoreLastLoginTime)\n      throws IOException {\n    // ensure the relogin is atomic to avoid leaving credentials in an\n    // inconsistent state.  prevents other ugi instances, SASL, and SPNEGO\n    // from accessing or altering credentials during the relogin.\n    synchronized(login.getSubjectLock()) {\n      // another racing thread may have beat us to the relogin.\n      if (login == getLogin()) {\n        unprotectedRelogin(login, ignoreLastLoginTime);\n      }\n    }\n  }\n\n  private void unprotectedRelogin(HadoopLoginContext login,","sourceCodeStart":1310,"sourceCodeEnd":1346,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java#L1310-L1346","documentation":"reloginFromTicketCache requires a login context on the UGI. If the auth method is ticket-based (isFromTicket() true) but getLogin() returns null, it throws KerberosAuthException(MUST_FIRST_LOGIN) - the mirror of the keytab variant.","triggerScenarios":"Calling ugi.reloginFromTicketCache() on a UGI not produced by loginUserFromTicketCache - e.g., a deserialized/copied login UGI, or one whose authentication method was switched to KERBEROS after simple login.","commonSituations":"Code that grabs getLoginUser() before Kerberos was enabled and later calls reloginFromTicketCache; UGI instances passed across process/task boundaries without their LoginContext.","solutions":["Use UserGroupInformation.loginUserFromTicketCache() (i.e., kinit first, then login) to obtain the UGI","Check UserGroupInformation.isLoginTicketBased() before calling reloginFromTicketCache","If the login context is missing, re-login from scratch rather than relogging"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!UserGroupInformation.isLoginTicketBased()) {\n  return; // nothing to relogin for this login user\n}\nUserGroupInformation.getLoginUser().reloginFromTicketCache();","typeGuard":"static boolean isTicketReloginable(UserGroupInformation ugi) {\n  return ugi.getAuthenticationMethod()\n      == UserGroupInformation.AuthenticationMethod.KERBEROS\n      && !ugi.isFromKeytab();\n}","tryCatchPattern":"try {\n  ugi.reloginFromTicketCache();\n} catch (KerberosAuthException e) {\n  if (e.getMessage().contains(\"login must be done first\")) {\n    ugi = UserGroupInformation.loginUserFromTicketCache();\n  } else { throw e; }\n}","preventionTips":["kinit before starting processes that will relogin from ticket cache","Check isLoginTicketBased() before scheduling ticket relogin","Re-login from scratch when a login context is unavailable"],"tags":["hadoop","kerberos","ugi","ticket-cache","relogin"],"backgroundTag":"operation-before-login","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}