apache/pulsar · error · SaslException

error while booting GSSAPI client

Error message

error while booting GSSAPI client

What it means

PulsarSaslClient creates the JVM SASL client (GSSAPI mechanism) inside Subject.doAs(...) via Sasl.createSaslClient; if that privileged action throws (PrivilegedActionException), the cause is wrapped in a SaslException with this message. It indicates the underlying SASL/GSSAPI/JNDI-Kerberos layer failed to instantiate the client mechanism — usually a Kerberos infrastructure problem (missing krb5.conf, bad principal/realm, no native GSS-API or JGSS failure), not a code bug.

Source

Thrown at pulsar-client-auth-sasl/src/main/java/org/apache/pulsar/client/impl/auth/PulsarSaslClient.java:85

        KerberosName serviceKerberosName = new KerberosName(serverPrincipal + "@" + clientKerberosName.getRealm());
        final String serviceName = serviceKerberosName.getServiceName();
        final String serviceHostname = serviceKerberosName.getHostName();
        final String clientPrincipalName = clientKerberosName.toString();
        log.info().attr("serverPrincipal", serverPrincipal)
                .log("Using JAAS/SASL/GSSAPI auth to connect to server");

        try {
            this.saslClient = Subject.doAs(clientSubject, new PrivilegedExceptionAction<SaslClient>() {
                @Override
                public SaslClient run() throws SaslException {
                    String[] mechs = {"GSSAPI"};
                    return Sasl.createSaslClient(mechs, clientPrincipalName, serviceName, serviceHostname, null,
                        new ClientCallbackHandler());
                }
            });
        } catch (PrivilegedActionException err) {
            log.error().exception(err.getCause()).log("GSSAPI client error");
            throw new SaslException("error while booting GSSAPI client", err.getCause());
        }

        if (saslClient == null) {
            throw new SaslException("Cannot create JVM SASL Client");
        }

    }

    public AuthData evaluateChallenge(final AuthData saslToken) throws AuthenticationException {
        if (saslToken == null) {
            throw new AuthenticationException("saslToken is null");
        }
        try {
            if (clientSubject != null) {
                final byte[] retval = Subject.doAs(clientSubject, new PrivilegedExceptionAction<byte[]>() {
                    @Override
                    public byte[] run() throws SaslException {
                        return saslClient.evaluateChallenge(saslToken.getBytes());

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the wrapped cause (err.getCause()) in logs — the 'GSSAPI client error' log line names the underlying GSSException.
  2. Ensure krb5.conf is present and valid (set -Djava.security.krb5.conf=/etc/krb5.conf) and the realm/KDC are reachable.
  3. Confirm a valid TGT exists (klist) and the JAAS subject's principal matches the keytab/kdc principal, including realm casing.
  4. Run with -Dsun.security.jgss.debug=true and -Dsun.security.spnego.debug=true to diagnose; verify the JVM includes the GSSAPI SASL provider (full JDK, not stripped JRE).

Example fix

// before
java -jar client.jar // GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)
// after
java -Djava.security.krb5.conf=/etc/krb5.conf \
     -Dsun.security.jgss.debug=true \
     -Djava.security.auth.login.config=/etc/pulsar/jaas.conf \
     -jar client.jar // after kinit -kt client.keytab user@REALM
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: pre-flight Kerberos environment checks
static void validateKerberosEnv() {
    String krb5 = System.getProperty("java.security.krb5.conf", "/etc/krb5.conf");
    if (!new File(krb5).canRead()) throw new IllegalStateException("krb5.conf missing: " + krb5);
    // probe that JGSS is functional:
    try {
        org.ietf.jgss.GSSManager factory = org.ietf.jgss.GSSManager.getInstance();
        factory.createName("user@REALM", org.ietf.jgss.GSSName.NT_USER_NAME);
    } catch (org.ietf.jgss.GSSException e) {
        throw new IllegalStateException("GSS init failed: " + e.getMessage(), e);
    }
}
// also verify a TGT: klist or Subject.getSubject(AccessController.getContext())
// has a KerberosTicket for krbtgt/REALM

Try / catch

try {
    PulsarSaslClient client = new PulsarSaslClient(host, serverType, subject);
} catch (SaslException e) {
    if (e.getMessage().contains("error while booting GSSAPI client")) {
        // e.getCause() is the GSSException/SaslException from createSaslClient
        log.error("GSSAPI init failed: {} — check krb5.conf, KDC reachability and TGT", e.getCause());
        // optionally re-kinit and retry once
    } else { throw e; }
}

Prevention

When it happens

Trigger: Sasl.createSaslClient({"GSSAPI"}, ...) throwing inside the privileged action — e.g. no default realm/krb5.conf found, client principal name unparseable, GSSException from JGSS initialization, or SASL provider missing GSSAPI support (atypical JVM).

Common situations: Missing or invalid /etc/krb5.conf (or -Djava.security.krb5.conf unset) so realm discovery fails; client principal's realm not resolvable; JDK without unrestricted JGSS/crypto policies; running in a minimal JRE lacking the SASL GSSAPI provider.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/87c068f885dadf19. Report an issue: GitHub.