t8y2/dbx · error

Kerberos realm is required for principal %s

Error message

Kerberos realm is required for principal %s

What it means

The principal had no '@' realm suffix and no realm could be supplied from the configured realm or the krb5.conf default_realm, so the principal cannot be fully qualified for Kerberos auth. Kerberos requires a realm; the library refuses to guess.

Source

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

	}
	return path, nil
}

func splitKerberosPrincipal(principal, configuredRealm, defaultRealm string) (string, string, error) {
	value := strings.TrimSpace(principal)
	realm := strings.TrimSpace(configuredRealm)
	if separator := strings.LastIndexByte(value, '@'); separator >= 0 {
		realm = value[separator+1:]
		value = value[:separator]
	}
	if value == "" {
		return "", "", fmt.Errorf("Kerberos principal is empty")
	}
	if realm == "" {
		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

View on GitHub (pinned to c0390bff16)

Solutions

  1. Include the realm in the principal: svc-cassandra@EXAMPLE.COM.
  2. Set the driver's kerberosrealm config option (or JAAS realm) to EXAMPLE.COM.
  3. Fix /etc/krb5.conf (or KRB5_CONFIG target) to define default_realm = EXAMPLE.COM so the default can be applied.
  4. Confirm the realm matches the KDC's realm, case-sensitive uppercase by convention.

Example fix

// before
principal="svc-cassandra"
// after
principal="svc-cassandra@EXAMPLE.COM" // or set kerberosrealm="EXAMPLE.COM"
Defensive patterns

Strategy: validation

Validate before calling

func principalHasRealm(p, configuredRealm string) bool {
	if strings.Contains(p, "@") { return true }
	return strings.TrimSpace(configuredRealm) != ""
}
// plus confirm /etc/krb5.conf has default_realm set when relying on the default

Type guard

func hasRealm(p string) bool {
	at := strings.LastIndexByte(strings.TrimSpace(p), '@')
	return at >= 0 && at < len(p)-1
}

Try / catch

if err := client.Finalize(); err != nil {
	if strings.Contains(err.Error(), "realm is required for principal") {
		log.Fatalf("qualify principal with @REALM or set kerberosrealm/default_realm")
	}
	return err
}

Prevention

When it happens

Trigger: splitKerberosPrincipal receives `svc-cassandra` (no @REALM), configuredRealm is empty, and defaultRealm (from krb5.conf parsing) is also empty — e.g. krb5.conf missing/unreadable or lacking default_realm.

Common situations: Short-form principals in configs; krb5.conf not mounted in containers so default_realm is unknown; missing kerberosrealm config option; cross-realm setups where only the short name was given.

Related errors


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