{"id":"5adc12e0395f704b","repo":"apache/kafka","slug":"principal-has-name-with-unexpected-format-servic","errorCode":null,"errorMessage":"Principal has name with unexpected format ${servicePrincipal}","messagePattern":"Principal has name with unexpected format (.+?)","errorType":"validation","errorClass":"KafkaException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/network/SaslChannelBuilder.java","lineNumber":382,"sourceCode":"        }\n    }\n\n    // As described in http://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/jgss-features.html:\n    // \"To enable Java GSS to delegate to the native GSS library and its list of native mechanisms,\n    // set the system property \"sun.security.jgss.native\" to true\"\n    // \"In addition, when performing operations as a particular Subject, for example, Subject.doAs(...)\n    // or Subject.doAsPrivileged(...), the to-be-used GSSCredential should be added to Subject's\n    // private credential set. Otherwise, the GSS operations will fail since no credential is found.\"\n    private void maybeAddNativeGssapiCredentials(Subject subject) {\n        boolean usingNativeJgss = Boolean.getBoolean(GSS_NATIVE_PROP);\n        if (usingNativeJgss && subject.getPrivateCredentials(GSSCredential.class).isEmpty()) {\n\n            final String servicePrincipal = SaslClientAuthenticator.firstPrincipal(subject);\n            KerberosName kerberosName;\n            try {\n                kerberosName = KerberosName.parse(servicePrincipal);\n            } catch (IllegalArgumentException e) {\n                throw new KafkaException(\"Principal has name with unexpected format \" + servicePrincipal);\n            }\n            final String servicePrincipalName = kerberosName.serviceName();\n            final String serviceHostname = kerberosName.hostName();\n\n            try {\n                GSSManager manager = gssManager();\n                // This Oid is used to represent the Kerberos version 5 GSS-API mechanism. It is defined in\n                // RFC 1964.\n                Oid krb5Mechanism = new Oid(\"1.2.840.113554.1.2.2\");\n                GSSName gssName = manager.createName(servicePrincipalName + \"@\" + serviceHostname, GSSName.NT_HOSTBASED_SERVICE);\n                GSSCredential cred = manager.createCredential(gssName,\n                        GSSContext.INDEFINITE_LIFETIME, krb5Mechanism, GSSCredential.ACCEPT_ONLY);\n                subject.getPrivateCredentials().add(cred);\n                log.info(\"Configured native GSSAPI private credentials for {}@{}\", serviceHostname, serviceHostname);\n            } catch (GSSException ex) {\n                log.warn(\"Cannot add private credential to subject; clients authentication may fail\", ex);\n            }\n        }","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/network/SaslChannelBuilder.java#L364-L400","documentation":"Thrown by SaslChannelBuilder.maybeAddNativeGssapiCredentials as a KafkaException when KerberosName.parse(servicePrincipal) raises IllegalArgumentException. This path runs only on the server side when sun.security.jgss.native=true and the subject has a GSSAPI/Kerberos principal but no GSSCredential; the code needs to parse the principal into primary/instance@REALM form to build a native GSS acceptor credential. A principal that does not match the expected Kerberos format cannot be turned into an acceptor name, so the broker aborts startup rather than silently failing client auth.","triggerScenarios":"Broker configured for SASL/GSSAPI with -Dsun.security.jgss.native=true, where the JAAS principal entry (KafkaServer { ... principal=\"...\" }) is not a valid KerberosName (missing '@REALM', contains illegal characters, or is a raw alias). KerberosName.parse throws IllegalArgumentException and SaslChannelBuilder wraps it.","commonSituations":"Setting the JAAS principal to a bare service alias like \"kafka\" instead of \"kafka/_HOST@REALM\"; copy-pasting a JAAS config that lost the realm; enabling native JGSS for the first time on a previously-java-only GSS setup where the principal string was lax.","solutions":["Set the JAAS principal to a fully-qualified Kerberos name of the form service/hostname@REALM (e.g. kafka/broker1.example.com@EXAMPLE.COM).","Confirm the realm suffix matches the KDC and that the principal exists in the KDC (kinit and kvno succeed).","If you did not intend to use native GSS, remove -Dsun.security.jgss.native=true so the pure-Java path (which does not call this parser) is used.","Re-run with the corrected JAAS config and restart the broker."],"exampleFix":"// before\nKafkaServer {\n  com.sun.security.auth.module.Krb5LoginModule required\n  principal=\"kafka\";\n};\n\n// after\nKafkaServer {\n  com.sun.security.auth.module.Krb5LoginModule required\n  principal=\"kafka/broker1.example.com@EXAMPLE.COM\";\n};","handlingStrategy":"validation","validationCode":"// Kerberos service principal must be primary/instance@REALM (instance optional).\nString servicePrincipal = /* from JAAS config or keytab */;\njava.util.regex.Pattern KRBFMT =\n    java.util.regex.Pattern.compile(\"^[^/@]+(/[^/@]+)?@[^/@]+$\");\nif (servicePrincipal == null || !KRBFMT.matcher(servicePrincipal).matches()) {\n    throw new IllegalArgumentException(\"Bad Kerberos principal format: \" + servicePrincipal);\n}\n// only reached when sun.security.jgss.native=true; format is enforced by KerberosName.parse","typeGuard":"// Narrow to a validated principal value object before handing to SASL setup.\nstatic Optional<String> validKerberosPrincipal(String p) {\n    if (p == null) return Optional.empty();\n    java.util.regex.Pattern KRBFMT =\n        java.util.regex.Pattern.compile(\"^[^/@]+(/[^/@]+)?@[^/@]+$\");\n    return KRBFMT.matcher(p).matches() ? Optional.of(p) : Optional.empty();\n}","tryCatchPattern":"try {\n    channelBuilder.configure(configs);   // native GSS path parses the principal\n} catch (KafkaException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Principal has name with unexpected format\")) {\n        log.error(\"Kerberos principal in JAAS config is malformed\", e);\n        failStartup(e);\n    }\n    throw e;\n}","preventionTips":["This path is only hit when sun.security.jgss.native=true; confirm you actually need native JGSS before enabling it.","Keep the Kerberos principal in JAAS config in standard form primary/instance@REALM (e.g. kafka/_HOST@EXAMPLE.COM).","Resolve _HOST placeholders against the actual hostname; a stale host mapping produces a malformed principal.","Verify the keytab principal with `klist -k` before deploying the JAAS config."],"tags":["kerberos","sasl","gssapi","jaas","broker-startup"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}