apache/hadoop · error · KerberosAuthException
loginUserFromKeyTab must be done first
Error message
loginUserFromKeyTab must be done first
What it means
The keytab logout path (logoutUserFromKeytab) requires a live HadoopLoginContext and a keytab file recorded on the UGI. If the UGI has Kerberos credentials but login==null or keytab==null - i.e., it never logged in from a keytab - it throws KerberosAuthException(MUST_FIRST_LOGIN_FROM_KEYTAB).
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java:1172
* @throws KerberosAuthException if a failure occurred in logout,
* or if the user did not log in by invoking loginUserFromKeyTab() before.
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
public void logoutUserFromKeytab() throws IOException {
if (!hasKerberosCredentials()) {
return;
}
// Shutdown the background task performing login renewal.
if (getKerberosLoginRenewalExecutor().isPresent()) {
getKerberosLoginRenewalExecutor().get().shutdownNow();
}
HadoopLoginContext login = getLogin();
String keytabFile = getKeytab();
if (login == null || keytabFile == null) {
throw new KerberosAuthException(MUST_FIRST_LOGIN_FROM_KEYTAB);
}
try {
LOG.debug("Initiating logout for {}", getUserName());
// hadoop login context internally locks credentials.
login.logout();
} catch (LoginException le) {
KerberosAuthException kae = new KerberosAuthException(LOGOUT_FAILURE, le);
kae.setUser(user.toString());
kae.setKeytabFile(keytabFile);
throw kae;
}
LOG.info("Logout successful for user " + getUserName()
+ " using keytab file " + keytabFile);
}
/**View on GitHub (pinned to 2add963021)
Solutions
- Only call logoutUserFromKeytab on UGI instances returned by loginUserFromKeytab(principal, keytabFile)
- Branch on ugi.isFromKeytab() (or UserGroupInformation.isLoginKeytabBased()) before logging out
- For ticket-cache sessions, let the TGT expire or kdestroy manually - there is no keytab logout
Example fix
// before
ugi.logoutUserFromKeytab(); // fails for ticket-cache UGIs
// after
if (ugi.isFromKeytab()) {
ugi.logoutUserFromKeytab();
} Defensive patterns
Strategy: validation
Validate before calling
if (!ugi.isFromKeytab()) {
// ticket-cache / external subjects cannot be keytab-logged-out
return;
} Type guard
static boolean isKeytabLogoutable(UserGroupInformation ugi) {
return ugi.isFromKeytab() && ugi.hasKerberosCredentials();
} Try / catch
try {
ugi.logoutUserFromKeytab();
} catch (KerberosAuthException e) {
LOG.warn("skip keytab logout for non-keytab UGI {}", ugi, e);
} Prevention
- Record how each UGI was created (keytab vs ticket vs subject) alongside the reference
- Gate logout paths on ugi.isFromKeytab()
- Do not serialize/copy UGIs and expect login state to survive
When it happens
Trigger: Calling ugi.logoutUserFromKeytab() on a UGI obtained via loginUserFromTicketCache, getUGIFromSubject, or getLoginUser under ticket-cache mode; also UGI instances reconstructed after serialization, whose login context did not survive.
Common situations: Generic cleanup/shutdown code assuming every Kerberos UGI came from a keytab; daemons mixing ticket-cache and keytab logins; job/task UGI copies.
Related errors
- Illegal principal name " + name + ": " + ioe.toString()
- Failed to find user in name " + subject
- Problem with Kerberos auth_to_local name configuration
- Invalid attribute value for hadoop.kerberos.min.seconds.befo
- Subject must not be null
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/f03ba3ab950c0879.
Report an issue: GitHub.