nathanmarz/storm · critical · IOException

Could not find a ' ' entry in this configuration: Client…

Error message

Could not find a '${AuthUtils.LOGIN_CONTEXT_CLIENT}' entry in this configuration: Client cannot start.

What it means

ClientCallbackHandler implements JAAS callbacks for the DIGEST-MD5 client side of Storm's digest authentication. In its constructor it asks the java.security.Configuration for the JAAS entry named AuthUtils.LOGIN_CONTEXT_CLIENT ("Client"); if no such section exists in the supplied JAAS configuration it throws this IOException, because the client cannot obtain its username/password and must refuse to start.

Solutions

  1. Add a 'Client { ... }' section to the JAAS config file passed via -Djava.security.auth.login.config, e.g. Client { org.apache.storm.security.auth.digest.MD5DigestLoginModule required username="user" password="pass"; };
  2. Verify the section name is exactly 'Client' with correct capitalization.
  3. Ensure the JAAS file is actually loaded: check -Djava.security.auth.login.config JVM option (or STORM_JAAS_CONF / java.security.auth.login.config in worker childopts) points to the right file on every node.
  4. If digest auth is not intended, switch storm.thrift.transport back to backtype.storm.security.auth.SimpleTransportPlugin so the digest ClientCallbackHandler is never used.

Example fix

// jaas.conf before (missing client section)
Server { com.myauth.MD5DigestLoginModule required user_admin="secret"; };
// after
Server { com.myauth.MD5DigestLoginModule required user_admin="secret"; };
Client { com.myauth.MD5DigestLoginModule required username="admin" password="secret"; };
Defensive patterns

Strategy: validation

Validate before calling

Configuration jaas = Configuration.getConfiguration();
if (jaas == null || jaas.getAppConfigurationEntry("Client") == null) {
    throw new IllegalStateException("JAAS config is missing the required 'Client' section");
}

Try / catch

try (InputStream in = new FileInputStream(jaasFile)) {
    // parse/verify sections before installing as the login configuration
} catch (IOException e) {
    throw new IllegalStateException("Client JAAS section missing: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Constructing ClientCallbackHandler with a Configuration whose JAAS config file has no section titled 'Client' (configuration.getAppConfigurationEntry(AuthUtils.LOGIN_CONTEXT_CLIENT) returns null), e.g. the storm.yaml 'storm.thrift.transport' points to a digest-MD5 transport but the jaas.conf passed via -Djava.security.auth.login.config lacks a 'Client {' block, or the section is misspelled.

Common situations: Deploying a Storm cluster with DigestMd5 authentication where the operator only configured a 'Server' section in jaas.conf and forgot the 'Client' section; running a topology on a worker node without the JAAS file on the classpath/path so the default config has no 'Client' entry; typos in the section name (lowercase 'client' — JAAS section names are case-sensitive).

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12). Data as JSON: /api/errors/6abdbbcab6c4aee1. Report an issue: GitHub.

Appendix: source

Thrown at storm-core/src/jvm/backtype/storm/security/auth/digest/ClientCallbackHandler.java:59

    private static final Logger LOG = LoggerFactory.getLogger(ClientCallbackHandler.class);
    private String _username = null;
    private String _password = null;

    /**
     * Constructor based on a JAAS configuration
     * 
     * For digest, you should have a pair of user name and password defined.
     * 
     * @param configuration
     * @throws IOException
     */
    public ClientCallbackHandler(Configuration configuration) throws IOException {
        if (configuration == null) return;
        AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(AuthUtils.LOGIN_CONTEXT_CLIENT);
        if (configurationEntries == null) {
            String errorMessage = "Could not find a '"+AuthUtils.LOGIN_CONTEXT_CLIENT
                    + "' entry in this configuration: Client cannot start.";
            throw new IOException(errorMessage);
        }

        _password = "";
        for(AppConfigurationEntry entry: configurationEntries) {
            if (entry.getOptions().get(USERNAME) != null) {
                _username = (String)entry.getOptions().get(USERNAME);
            }
            if (entry.getOptions().get(PASSWORD) != null) {
                _password = (String)entry.getOptions().get(PASSWORD);
            }
        }
    }

    /**
     * This method is invoked by SASL for authentication challenges
     * @param callbacks a collection of challenge callbacks 
     */
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

View on GitHub (pinned to cdb116e942)