juicedata/juicefs · error

unusable ccache: %s

Error message

unusable ccache: %s

What it means

Without a keytab, getKerberosClient uses the credential cache from KRB5CCNAME. The library only understands a bare file path or an explicit "FILE:/path" scheme; any other scheme (e.g. KCM:, DIR:, KEYRING:persistent) — or an unusable value while a ccache is required — returns "unusable ccache: %s". The krb5 library in use here only supports FILE-based caches.

Source

Thrown at pkg/object/hdfs_kerberos.go:80

		// 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()
		if err != nil {
			return nil, err
		}

		ccachePath = fmt.Sprintf("/tmp/krb5cc_%s", u.Uid)
	}

	ccache, err := credentials.LoadCCache(ccachePath)
	if err != nil {
		return nil, err
	}

	client, err := krb.NewFromCCache(ccache, cfg, krbSettings...)
	if err != nil {
		return nil, err

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Re-kinit into a FILE cache and point KRB5CCNAME at it: kinit -c FILE:/tmp/krb5cc_juicefs principal && export KRB5CCNAME=FILE:/tmp/krb5cc_juicefs.
  2. Convert the existing cache: kcm/DIR caches can be exported via kinit -R or by re-authenticating with KRB5CCNAME=FILE:... set.
  3. If the cache is not needed, unset KRB5CCNAME so the library falls back to user.Current()'s home default path.
  4. Prefer the keytab route (KRB5KEYTAB + KRB5PRINCIPAL) which bypasses the ccache entirely.

Example fix

// before
export KRB5CCNAME=KCM:1000
// after
kinit -c FILE:/tmp/krb5cc_juicefs juicefs/host.example.com@EXAMPLE.COM
export KRB5CCNAME=FILE:/tmp/krb5cc_juicefs
Defensive patterns

Strategy: validation

Validate before calling

cc := os.Getenv("KRB5CCNAME")
if strings.Contains(cc, ":") && !strings.HasPrefix(cc, "FILE:") {
    return fmt.Errorf("unsupported ccache type %q; only FILE caches are supported", cc)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "unusable ccache") {
    logger.Fatalf("Unsupported KRB5CCNAME: %v — re-kinit into a FILE cache", err)
}

Prevention

When it happens

Trigger: getKerberosClient called with KRB5CCNAME set to a non-FILE scheme such as "KCM:1000", "DIR::/tmp/krb5cc_...", or "KEYRING:persistent:1000"; the value contains ":" but does not start with "FILE:".

Common situations: Modern Linux desktops / SSSD defaulting KRB5CCNAME to KCM or KEYRING; container runtimes inheriting DIR-style caches; MIT krb5 1.11+ default ccaches differing from the JuiceFS expectation.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


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