t8y2/dbx · error

Kerberos keytab %s contains %d principals; configure kerbero

Error message

Kerberos keytab %s contains %d principals; configure kerberosprincipal explicitly

What it means

principalFromKeytab extracts a Kerberos principal from a keytab file by collecting the distinct principals across all keytab entries. It refuses to guess when the keytab contains more than one distinct principal, because picking the wrong one would authenticate as the wrong identity. The error tells you to set kerberosprincipal explicitly so the driver knows which principal to use.

Source

Thrown at agents/drivers/cassandra-go/kerberos.go:577

		realm = strings.TrimSpace(defaultRealm)
	}
	if realm == "" {
		return "", "", fmt.Errorf("Kerberos realm is required for principal %s", principal)
	}
	return value, realm, nil
}

func principalFromKeytab(path string) (string, error) {
	loadedKeytab, err := keytab.Load(path)
	if err != nil {
		return "", fmt.Errorf("load Kerberos keytab %s: %w", path, err)
	}
	principals := map[string]struct{}{}
	for _, entry := range loadedKeytab.Entries {
		principals[entry.Principal.String()] = struct{}{}
	}
	if len(principals) != 1 {
		return "", fmt.Errorf("Kerberos keytab %s contains %d principals; configure kerberosprincipal explicitly", path, len(principals))
	}
	for principal := range principals {
		return principal, nil
	}
	return "", fmt.Errorf("Kerberos keytab %s contains no principals", path)
}

func defaultKerberosConfigPath() string {
	if runtime.GOOS == "windows" {
		if windowsDirectory := os.Getenv("WINDIR"); windowsDirectory != "" {
			return filepath.Join(windowsDirectory, "krb5.ini")
		}
	}
	return "/etc/krb5.conf"
}

func defaultKerberosCCachePath() string {
	if value := os.Getenv("KRB5CCNAME"); value != "" {

View on GitHub (pinned to c0390bff16)

Solutions

  1. Set the kerberosprincipal option explicitly to the exact principal string that appears in the keytab.
  2. Use klist -k <path> to list the principals in the keytab and pick the correct one.
  3. If no principal is needed from this keytab, point the keytab configuration at a keytab containing only the intended principal.

Example fix

// before
kerberos: keytab=/etc/krb5.keytab (no principal set; keytab has 3 principals)
// after
kerberos: keytab=/etc/krb5.keytab, kerberosprincipal=svc-cassandra@EXAMPLE.COM
Defensive patterns

Strategy: validation

Validate before calling

out, err := exec.Command("klist", "-k", keytabPath).Output()
if err != nil { return err }
principals := map[string]struct{}{}
for _, line := range strings.Split(string(out), "\n") {
    if f := strings.Fields(line); len(f) >= 4 { principals[f[3]] = struct{}{} }
}
if len(principals) != 1 {
    return fmt.Errorf("keytab has %d principals; set kerberosprincipal", len(principals))
}

Try / catch

if err != nil && strings.Contains(err.Error(), "configure kerberosprincipal explicitly") {
    // surface config guidance to the operator instead of retrying
}

Prevention

When it happens

Trigger: Calling selectKeytabCredential (via finalize) when kerberosprincipal is unset and the keytab at the configured path loads successfully but its Entries map to 2+ distinct entry.Principal.String() values.

Common situations: Reusing a host keytab (e.g. /etc/krb5.keytab) that holds entries for host/FQDN, HTTP/FQDN and user service principals; merging multiple service keytabs into one file; shared keytabs used by several services on one host.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/eb602d8b157b75d0. Report an issue: GitHub.