juicedata/juicefs · error

unusable kerberos principal: %s

Error message

unusable kerberos principal: %s

What it means

When a keytab is provided, getKerberosClient requires KRB5PRINCIPAL in the form "primary/instance@realm". It splits the principal at "@" and demands exactly two parts. Anything else — missing realm, multiple @ signs, or an empty KRB5PRINCIPAL — fails with "unusable kerberos principal: %s". The library needs both the username (primary/instance) and realm to construct the krb5 client.

Source

Thrown at pkg/object/hdfs_kerberos.go:65

		if err != nil {
			return nil, fmt.Errorf("error decoding Base64 encoded data %s", err)
		}
		kt = new(keytab.Keytab)
		err = kt.Unmarshal(decodedKeytab)
		if err != nil {
			return nil, err
		}
	} else if keytabPath != "" {
		kt, err = keytab.Load(keytabPath)
		if err != nil {
			return nil, err
		}
	}
	if kt != nil {
		// e.g. KRB5PRINCIPAL="primary/instance@realm"
		sp := strings.Split(principal, "@")
		if len(sp) != 2 {
			return nil, fmt.Errorf("unusable kerberos principal: %s", principal)
		}
		username, realm := sp[0], sp[1]
		logger.Infof("username: %s, realm: %s", username, realm)
		client := krb.NewWithKeytab(username, realm, kt, cfg, krbSettings...)
		return client, nil
	}

	// Determine the ccache location from the environment, falling back to the
	// default location.
	ccachePath := os.Getenv("KRB5CCNAME")
	if strings.Contains(ccachePath, ":") {
		if strings.HasPrefix(ccachePath, "FILE:") {
			ccachePath = strings.SplitN(ccachePath, ":", 2)[1]
		} else {
			return nil, fmt.Errorf("unusable ccache: %s", ccachePath)
		}
	} else if ccachePath == "" {
		u, err := user.Current()

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Set KRB5PRINCIPAL to the full principal exactly as in the keytab, e.g. KRB5PRINCIPAL="juicefs/host.example.com@EXAMPLE.COM".
  2. Confirm the exact principal with klist -kte /path/to/keytab and copy it verbatim (case-sensitive realm).
  3. Remove any stray "@" characters or whitespace from the value.
  4. If only a ccache is used (no keytab), clear the keytab env var so the ccache path is taken instead.

Example fix

// before
export KRB5PRINCIPAL="juicefs"            # no @realm
// after
export KRB5PRINCIPAL="juicefs/host.example.com@EXAMPLE.COM"
Defensive patterns

Strategy: validation

Validate before calling

p := os.Getenv("KRB5PRINCIPAL")
if ktSet := os.Getenv("KRB5KEYTAB") != ""; ktSet {
    parts := strings.Split(p, "@")
    if p == "" || len(parts) != 2 || parts[0] == "" || parts[1] == "" {
        return fmt.Errorf("KRB5PRINCIPAL must be 'primary/instance@REALM', got %q", p)
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "unusable kerberos principal") {
    logger.Fatalf("Bad KRB5PRINCIPAL: %v — use full principal like user/host@REALM", err)
}

Prevention

When it happens

Trigger: getKerberosClient called (keytab present) with KRB5PRINCIPAL unset/empty, or set to a short-form principal like "hdfs/host" without "@REALM", or containing extra "@" characters (e.g. escaped or duplicated).

Common situations: Using the bare username instead of the full principal; forgetting the realm when the keytab was exported for a multi-realm setup; copying a principal with a trailing comment; KRB5PRINCIPAL simply not set while the keytab is.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/08d83cd5e826b535. Report an issue: GitHub.