apache/hadoop · error · KerberosAuthException

login must be done first

Error message

login must be done first

What it means

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.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java:1328

   * The Subject field of this UserGroupInformation object is updated to have
   * the new credentials.
   * @throws IOException raised on errors performing I/O.
   * @throws KerberosAuthException on a failure
   */
  @InterfaceAudience.Public
  @InterfaceStability.Evolving
  public void reloginFromTicketCache() throws IOException {
    reloginFromTicketCache(false);
  }

  private void reloginFromTicketCache(boolean ignoreLastLoginTime)
      throws IOException {
    if (!shouldRelogin() || !isFromTicket()) {
      return;
    }
    HadoopLoginContext login = getLogin();
    if (login == null) {
      throw new KerberosAuthException(MUST_FIRST_LOGIN);
    }
    relogin(login, ignoreLastLoginTime);
  }

  private void relogin(HadoopLoginContext login, boolean ignoreLastLoginTime)
      throws IOException {
    // ensure the relogin is atomic to avoid leaving credentials in an
    // inconsistent state.  prevents other ugi instances, SASL, and SPNEGO
    // from accessing or altering credentials during the relogin.
    synchronized(login.getSubjectLock()) {
      // another racing thread may have beat us to the relogin.
      if (login == getLogin()) {
        unprotectedRelogin(login, ignoreLastLoginTime);
      }
    }
  }

  private void unprotectedRelogin(HadoopLoginContext login,

View on GitHub (pinned to 2add963021)

Solutions

  1. Use UserGroupInformation.loginUserFromTicketCache() (i.e., kinit first, then login) to obtain the UGI
  2. Check UserGroupInformation.isLoginTicketBased() before calling reloginFromTicketCache
  3. If the login context is missing, re-login from scratch rather than relogging
Defensive patterns

Strategy: validation

Validate before calling

if (!UserGroupInformation.isLoginTicketBased()) {
  return; // nothing to relogin for this login user
}
UserGroupInformation.getLoginUser().reloginFromTicketCache();

Type guard

static boolean isTicketReloginable(UserGroupInformation ugi) {
  return ugi.getAuthenticationMethod()
      == UserGroupInformation.AuthenticationMethod.KERBEROS
      && !ugi.isFromKeytab();
}

Try / catch

try {
  ugi.reloginFromTicketCache();
} catch (KerberosAuthException e) {
  if (e.getMessage().contains("login must be done first")) {
    ugi = UserGroupInformation.loginUserFromTicketCache();
  } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: Code that grabs getLoginUser() before Kerberos was enabled and later calls reloginFromTicketCache; UGI instances passed across process/task boundaries without their LoginContext.

Related errors


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