apache/beam · error · RuntimeException

Could not access keytab file. Make sure that the sasl.jaas.c

Error message

Could not access keytab file. Make sure that the sasl.jaas.config config property is set correctly.

What it means

After downloading the keytab to a local path, KerberosConsumerFactoryFn tightens its POSIX permissions to owner-read-only. If Files.setPosixFilePermissions throws IOException (file missing or filesystem without POSIX support), it rethrows a RuntimeException telling the user to check sasl.jaas.config. The message points at the config because the local keytab path derives from it.

Source

Thrown at sdks/java/extensions/kafka-factories/src/main/java/org/apache/beam/sdk/extensions/kafka/factories/KerberosConsumerFactoryFn.java:80

    // property will have had it's value replaced with a local directory.
    // We don't need to worry about the external bucket prefix in this case.
    try {
      String jaasConfig = (String) config.get(JAAS_CONFIG_PROPERTY);
      String localKeytabPath = "";
      if (jaasConfig != null && !jaasConfig.isEmpty()) {
        localKeytabPath =
            jaasConfig.substring(
                jaasConfig.indexOf("keyTab=\"") + 8, jaasConfig.lastIndexOf("\" principal"));
      }

      // Set the permissions on the file to be as strict as possible for security reasons. The
      // keytab contains sensitive information and should be as locked down as possible.
      Path path = Paths.get(localKeytabPath);
      Set<PosixFilePermission> perms = new HashSet<>();
      perms.add(PosixFilePermission.OWNER_READ);
      Files.setPosixFilePermissions(path, perms);
    } catch (IOException e) {
      throw new RuntimeException(
          "Could not access keytab file. Make sure that the sasl.jaas.config config property "
              + "is set correctly.",
          e);
    }
    return new KafkaConsumer<>(config);
  }

  @Override
  protected void downloadAndProcessExtraFiles() throws IOException {
    synchronized (lock) {
      // we only want a new krb5 file if there is not already one present.
      if (localKrb5ConfPath.isEmpty()) {
        if (this.krb5ConfigPath != null && !this.krb5ConfigPath.isEmpty()) {
          String localPath =
              super.getBaseDirectory() + "/" + LOCAL_FACTORY_TYPE + "/" + "krb5.conf";
          localKrb5ConfPath = downloadExternalFile(this.krb5ConfigPath, localPath);

          System.setProperty("java.security.krb5.conf", localKrb5ConfPath);

View on GitHub (pinned to 12126d8942)

Solutions

  1. Verify sasl.jaas.config correctly references the keytab secret so the file is downloaded to localKeytabPath before this code runs
  2. Check the chained IOException cause — FileNotFoundException means the keytab never landed at localKeytabPath
  3. Ensure the worker staging directory is on a POSIX-supporting filesystem
  4. Log/inspect localKeytabPath and confirm the file exists before constructing the consumer

Example fix

// before
props.put("sasl.jaas.config", "com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab=\"MISSING\" ...");
// after
props.put("sasl.jaas.config", "com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab=\"/tmp/keytab-<factory>/krb5.keytab\" ..."); // path produced by secret processing
Defensive patterns

Strategy: try-catch

Validate before calling

java
if (!config.containsKey("sasl.jaas.config") || config.get("sasl.jaas.config").isEmpty()) {
  throw new IllegalArgumentException("sasl.jaas.config must be set with a valid keyTab path");
}

Try / catch

java
try {
  KafkaConsumer<String,String> c = factoryFn.createObject(config);
} catch (RuntimeException ex) {
  if (ex.getMessage().startsWith("Could not access keytab file")) {
    log.severe("Keytab inaccessible at local path: " + ex.getCause());
  }
}

Prevention

When it happens

Trigger: The keytab referenced in sasl.jaas.config was not written to localKeytabPath (secret processing failed or path mismatch), or the worker filesystem (e.g. some Windows/network mounts) doesn't support POSIX permissions.

Common situations: Missing or empty sasl.jaas.config key; secret download silently skipped; container using a volume that doesn't support POSIX perms; typo'd keytab path template.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/efd9e547d1f5dc36. Report an issue: GitHub.