apache/hadoop · error · IllegalStateException

Subject does not contain a valid User

Error message

Subject does not contain a valid User

What it means

UserGroupInformation(Subject) takes the first User-class principal from the subject and requires it to exist with a non-null name. A Subject never produced by a Hadoop login is invalid here; note that a Subject with no User principal at all usually surfaces as NoSuchElementException from iterator().next() on the same line, while this IllegalStateException fires when a User principal exists but its name is null. Either way the Subject is not a Hadoop-populated one.

Source

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

  private void setLastLogin(long loginTime) {
    user.setLastLogin(loginTime);
  }

  /**
   * Create a UserGroupInformation for the given subject.
   * This does not change the subject or acquire new credentials.
   *
   * The creator of subject is responsible for renewing credentials.
   * @param subject the user's subject
   */
  UserGroupInformation(Subject subject) {
    this.subject = subject;
    // do not access ANY private credentials since they are mutable
    // during a relogin.  no principal locking necessary since
    // relogin/logout does not remove User principal.
    this.user = subject.getPrincipals(User.class).iterator().next();
    if (user == null || user.getName() == null) {
      throw new IllegalStateException("Subject does not contain a valid User");
    }
  }

  /**
   * checks if logged in using kerberos
   * @return true if the subject logged via keytab or has a Kerberos TGT
   */
  public boolean hasKerberosCredentials() {
    return user.getAuthenticationMethod() == AuthenticationMethod.KERBEROS;
  }

  /**
   * Return the current user, including any doAs in the current stack.
   * @return the current user
   * @throws IOException if login fails
   */
  @InterfaceAudience.Public
  @InterfaceStability.Evolving

View on GitHub (pinned to 2add963021)

Solutions

  1. Use UserGroupInformation.getUGIFromSubject(subject) - it runs the Hadoop login modules that add the User principal
  2. Obtain UGIs from loginUserFromKeytab/loginUserFromTicketCache/getLoginUser which populate the User principal correctly
  3. For synthetic identities use createRemoteUser/createProxyUser, which build a well-formed Subject

Example fix

// before
Subject s = loginContext.getSubject();
UserGroupInformation ugi = new UserGroupInformation(s); // package-visible, fragile
// after
UserGroupInformation ugi =
    UserGroupInformation.getUGIFromSubject(loginContext.getSubject());
Defensive patterns

Strategy: type-guard

Validate before calling

if (subject.getPrincipals(UserGroupInformation.User.class).isEmpty()) {
  throw new IllegalArgumentException(
      "subject lacks a User principal; use getUGIFromSubject/loginUserFromKeytab");
}

Type guard

static boolean hasValidUserPrincipal(Subject subject) {
  for (Principal p : subject.getPrincipals()) {
    if (p instanceof UserGroupInformation.User
        && ((UserGroupInformation.User) p).getName() != null) {
      return true;
    }
  }
  return false;
}

Prevention

When it happens

Trigger: Directly constructing UserGroupInformation with a Subject built outside Hadoop - a raw JAAS login Subject holding only KerberosPrincipal, a Subject with just RealUser/principals, or a mock/test Subject with a null-named User.

Common situations: Integration tests assembling Subjects by hand; application code calling the package-visible constructor after an upgrade; SPNEGO filters wrapping non-Hadoop subjects.

Related errors


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