{"record":{"id":"5b1a56fa5e0efaa8","repo":"apache/hadoop","slug":"kerberos-principal-name-does-not-have-the-expected-5b1a56","errorCode":null,"errorMessage":"Kerberos principal name does NOT have the expected hostname part: ","messagePattern":"Kerberos principal name does NOT have the expected hostname part: ","errorType":"exception","errorClass":"AccessControlException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SaslRpcServer.java","lineNumber":141,"sourceCode":"  }\n  \n  @InterfaceAudience.Private\n  @InterfaceStability.Unstable\n  public SaslServer create(final Connection connection,\n                           final Map<String,?> saslProperties,\n                           SecretManager<TokenIdentifier> secretManager\n      ) throws IOException, InterruptedException {\n    UserGroupInformation ugi = null;\n    final CallbackHandler callback;\n    switch (authMethod) {\n      case TOKEN: {\n        callback = new SaslDigestCallbackHandler(secretManager, connection);\n        break;\n      }\n      case KERBEROS: {\n        ugi = UserGroupInformation.getCurrentUser();\n        if (serverId.isEmpty()) {\n          throw new AccessControlException(\n              \"Kerberos principal name does NOT have the expected \"\n                  + \"hostname part: \" + ugi.getUserName());\n        }\n        callback = new SaslGssCallbackHandler();\n        break;\n      }\n      default:\n        // we should never be able to get here\n        throw new AccessControlException(\n            \"Server does not support SASL \" + authMethod);\n    }\n    \n    final SaslServer saslServer;\n    if (ugi != null) {\n      saslServer = ugi.doAs(\n        new PrivilegedExceptionAction<SaslServer>() {\n          @Override\n          public SaslServer run() throws SaslException  {","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/SaslRpcServer.java#L123-L159","documentation":"When SaslRpcServer.create handles KERBEROS, the server principal from UserGroupInformation.getCurrentUser() is split on / and @ (the constructor maps parts[1] to serverId). If the principal has no host component, such as hdfs@REALM instead of hdfs/_HOST@REALM, serverId is empty and the server throws AccessControlException because no service principal can be formed for the SASL GSSAPI mechanism.","triggerScenarios":"Starting a Kerberos SASL RPC server while the current UGI was logged in from a keytab whose principal is a bare user principal (no service/host part); test or embedded code that calls UserGroupInformation.loginUserFromKeytab('user@REALM', keytab) and then builds a SaslRpcServer with authMethod KERBEROS.","commonSituations":"dfs.namenode.kerberos.principal / dfs.datanode.kerberos.principal set to a bare user principal; principals renamed without the /_HOST part during a Kerberos migration; auth_to_local rules rewriting the principal before the server reads it.","solutions":["Set the daemon principal to service/_HOST@REALM (e.g. nn/_HOST@EXAMPLE.COM) so the host part is present after substitution","Verify the keytab with klist -kt <keytab> and confirm it contains a service principal with a host component","Check hadoop.security.auth_to_local rules are not stripping the host part unexpectedly","In custom code, log UserGroupInformation.getCurrentUser() immediately before SaslRpcServer creation and confirm it has three components (service/host@REALM)"],"exampleFix":"<!-- before -->\n<property><name>dfs.namenode.kerberos.principal</name><value>nn@EXAMPLE.COM</value></property>\n\n<!-- after -->\n<property><name>dfs.namenode.kerberos.principal</name><value>nn/_HOST@EXAMPLE.COM</value></property>","handlingStrategy":"validation","validationCode":"String principal = conf.get(\"dfs.namenode.kerberos.principal\", \"\");\nString[] parts = principal.split(\"[/@]\", 3);\nif (UserGroupInformation.isSecurityEnabled()\n    && (parts.length < 3 || parts[1].isEmpty())) {\n  throw new IllegalStateException(\n      \"Kerberos principal must have a host component (service/_HOST@REALM): \" + principal);\n}","typeGuard":"static boolean principalHasHostPart(String principal) {\n  String[] p = principal == null ? new String[0] : principal.split(\"[/@]\", 3);\n  return p.length == 3 && !p[1].isEmpty();\n}","tryCatchPattern":null,"preventionTips":["Always write daemon principals as service/_HOST@REALM so the host is substituted at login","Validate principal shape in startup scripts before launching daemons","Verify keytab contents with klist -kt as part of security config CI"],"tags":["kerberos","sasl","principal","server-startup"],"backgroundTag":"kerberos-principal-misconfigured","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}