apache/hadoop · critical · IllegalArgumentException

signer.secret.provider.zookeeper.path must be specified

Error message

signer.secret.provider.zookeeper.path must be specified

What it means

ZKSignerSecretProvider shares cookie-signing secrets across a cluster via ZooKeeper, storing them under the znode given by signer.secret.provider.zookeeper.path. During startup initialization this required property is read; a missing value throws IllegalArgumentException naming the property, aborting provider init.

Source

Thrown at hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/ZKSignerSecretProvider.java:179

  @Override
  public void init(Properties config, ServletContext servletContext,
          long tokenValidity) throws Exception {
    Object curatorClientObj = servletContext.getAttribute(
            ZOOKEEPER_SIGNER_SECRET_PROVIDER_CURATOR_CLIENT_ATTRIBUTE);
    if (curatorClientObj != null
            && curatorClientObj instanceof CuratorFramework) {
      client = (CuratorFramework) curatorClientObj;
    } else {
      client = createCuratorClient(config);
      servletContext.setAttribute(
          ZOOKEEPER_SIGNER_SECRET_PROVIDER_CURATOR_CLIENT_ATTRIBUTE, client);
    }
    this.tokenValidity = tokenValidity;
    shouldDisconnect = Boolean.parseBoolean(
            config.getProperty(DISCONNECT_FROM_ZOOKEEPER_ON_SHUTDOWN, "true"));
    path = config.getProperty(ZOOKEEPER_PATH);
    if (path == null) {
      throw new IllegalArgumentException(ZOOKEEPER_PATH
              + " must be specified");
    }
    try {
      nextRolloverDate = System.currentTimeMillis() + tokenValidity;
      // everyone tries to do this, only one will succeed and only when the
      // znode doesn't already exist.  Everyone else will synchronize on the
      // data from the znode
      client.create().creatingParentsIfNeeded()
              .forPath(path, generateZKData(generateRandomSecret(),
              generateRandomSecret(), null));
      zkVersion = 0;
      LOG.info("Creating secret znode");
    } catch (KeeperException.NodeExistsException nee) {
      LOG.info("The secret znode already exists, retrieving data");
    }
    // Synchronize on the data from the znode
    // passing true tells it to parse out all the data for initing
    pullFromZK(true);

View on GitHub (pinned to 2add963021)

Solutions

  1. Add signer.secret.provider.zookeeper.path (e.g. /hadoop-auth-secret) to the AuthenticationFilter configuration wherever zookeeper provider is enabled
  2. Prefer the prefixed forms (signer.secret.provider.zookeeper.*) applied via the hadoop.auth.config.* prefix so they reach the filter
  3. Restart the webapp after adding the property

Example fix

# before
signer.secret.provider=zookeeper
# (no zookeeper.path set -> IllegalArgumentException)

# after
signer.secret.provider=zookeeper
signer.secret.provider.zookeeper.path=/hadoop-auth-secret
Defensive patterns

Strategy: validation

Validate before calling

String path = props.getProperty("signer.secret.provider.zookeeper.path");
if ("zookeeper".equals(props.getProperty("signer.secret.provider")) && path == null) {
  throw new IllegalArgumentException("zookeeper path required when using ZKSignerSecretProvider");
}

Try / catch

config/init error — fail startup with a clear message listing the missing property; catching to default to a random secret would break cross-node SSO

Prevention

When it happens

Trigger: Configuring signer.secret.provider = zookeeper (for HA authentication filter) in the servlet/filter config without also setting signer.secret.provider.zookeeper.path.

Common situations: Enabling ZooKeeper-based secret sharing for multiple UI/proxy nodes and forgetting the path property; properties split across files where the auth filter config file lacks the path entry.

Related errors


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