apache/hadoop · error · IOException

Running in secure mode, but config doesn't have a keytab for

Error message

Running in secure mode, but config doesn't have a keytab for key: 

What it means

SecurityUtil.login(conf, keytabFileKey, userNameKey, hostname) performs keytab login for daemons. When Kerberos is enabled (UserGroupInformation.isSecurityEnabled) but conf.get(keytabFileKey) is null or empty, it throws IOException naming the missing config key (e.g. dfs.namenode.keytab.file) so the operator knows exactly which property to set.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SecurityUtil.java:328

   *          the key to look for keytab file in conf
   * @param userNameKey
   *          the key to look for user's Kerberos principal name in conf
   * @param hostname
   *          hostname to use for substitution
   * @throws IOException if the config doesn't specify a keytab
   */
  @InterfaceAudience.Public
  @InterfaceStability.Evolving
  public static void login(final Configuration conf,
      final String keytabFileKey, final String userNameKey, String hostname)
      throws IOException {
    
    if(! UserGroupInformation.isSecurityEnabled()) 
      return;
    
    String keytabFilename = conf.get(keytabFileKey);
    if (keytabFilename == null || keytabFilename.length() == 0) {
      throw new IOException(
          "Running in secure mode, but config doesn't have a keytab for key: " + keytabFileKey);
    }

    String principalConfig = conf.get(userNameKey, System
        .getProperty("user.name"));
    String principalName = SecurityUtil.getServerPrincipal(principalConfig,
        hostname);
    UserGroupInformation.loginUserFromKeytab(principalName, keytabFilename);
  }

  /**
   * create the service name for a Delegation token
   * @param uri of the service
   * @param defPort is used if the uri lacks a port
   * @return the token service, or null if no authority
   * @see #buildTokenService(InetSocketAddress)
   */
  public static String buildDTServiceName(URI uri, int defPort) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Set the keytab property named in the message to the path of the daemon's keytab file
  2. Set the matching principal property (userNameKey, e.g. dfs.namenode.kerberos.principal) as well
  3. Confirm the file exists and is readable by the daemon user: klist -kt <path>
  4. Redeploy identical configs to all nodes and restart the daemon

Example fix

<!-- before -->
<property><name>dfs.namenode.keytab.file</name><value></value></property>

<!-- after -->
<property><name>dfs.namenode.keytab.file</name><value>/etc/security/keytab/nn.service.keytab</value></property>
Defensive patterns

Strategy: validation

Validate before calling

String keytab = conf.get(keytabFileKey);
if (UserGroupInformation.isSecurityEnabled()
    && (keytab == null || keytab.isEmpty())) {
  throw new IOException("Missing required keytab config: " + keytabFileKey
      + " while Kerberos is enabled");
}
SecurityUtil.login(conf, keytabFileKey, userNameKey, hostname);

Prevention

When it happens

Trigger: hadoop.security.authentication=kerberos while the daemon keytab property (dfs.namenode.keytab.file, mapreduce.jobhistory.keytab.file, etc.) is unset, empty, or misspelled, and the daemon calls SecurityUtil.login at startup.

Common situations: Enabling security on an existing cluster but forgetting daemon keytab configs; XML property-name typos; an empty value overriding a valid one later in the config chain.

Related errors


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