k3s-io/k3s · error

invalid token CA hash length

Error message

invalid token CA hash length

What it means

k3s node tokens have the form K10<ca-hash>::<credentials>. When the CA hash segment is present and non-empty, its length must equal caHashLength = sha256.Size*2 = 64 hex characters (pkg/clientaccess/token.go:29) — the hex-encoded SHA-256 of the server CA cert. Any other non-zero length means the hash was truncated or mangled, and parsing fails.

Source

Thrown at pkg/clientaccess/token.go:239

	if !strings.HasPrefix(token, tokenPrefix) {
		_, err := kubeadm.NewBootstrapTokenString(token)
		if err != nil {
			token = tokenPrefix + ":::" + token
		} else {
			token = tokenPrefix + "::" + token
		}
	}

	// Strip off the prefix.
	token = token[len(tokenPrefix):]

	// Split into CA hash and creds.
	parts := strings.SplitN(token, "::", 2)
	token = parts[0]
	if len(parts) > 1 {
		hashLen := len(parts[0])
		if hashLen > 0 && hashLen != caHashLength {
			return nil, errors.New("invalid token CA hash length")
		}
		info.caHash = parts[0]
		token = parts[1]
	}

	// Try to parse creds as bootstrap token string; fall back to basic auth.
	// If neither works, error.
	bts, err := kubeadm.NewBootstrapTokenString(token)
	if err != nil {
		parts = strings.SplitN(token, ":", 2)
		if len(parts) != 2 || len(parts[1]) == 0 {
			return nil, errors.New("invalid token format")
		}
		info.Username = parts[0]
		info.Password = parts[1]
	} else {
		info.BootstrapTokenString = bts
	}

View on GitHub (pinned to 6ba341e396)

Solutions

  1. Re-copy the full token from the seed server (`cat /var/lib/rancher/k3s/server/token` or `k3s token create --ttl 0`) and pass it verbatim
  2. Check length: the hash segment between 'K10' and '::' must be exactly 64 hex characters
  3. Store and inject tokens via files/secrets rather than copy-paste to avoid clipping

Example fix

# before (hash truncated to 8 chars)
K10deadbeef::abcdef.0123456789abcdef

# after (full 64-char sha256 hex hash)
K10e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855::abcdef.0123456789abcdef
Defensive patterns

Strategy: validation

Validate before calling

// k3s node token: K10[<64-hex sha256 CA hash>]::<bootstrap-token|user:pass>
var k3sTokenRe = regexp.MustCompile(`^K10([0-9a-f]{64})?::([^:]+|[^:]{6}\.[a-z0-9]{16}|[^:]+:[^:]+)$`)
if !k3sTokenRe.MatchString(token) {
    return fmt.Errorf("token failed pre-validation; expected hash segment of exactly 64 hex chars")
}

Type guard

func validK3sTokenHash(token string) bool {
    s := strings.TrimPrefix(token, "K10")
    hash := strings.SplitN(s, "::", 2)[0]
    return hash == "" || len(hash) == 64
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "invalid token CA hash length") {
        // token was clipped or mangled in transit; re-fetch from source of truth
        token = fetchFreshToken()
    }
}

Prevention

When it happens

Trigger: Passing a token like `K10abc123::abcdef.0123456789abcdef` where the hash part is not exactly 64 chars; tokens truncated by copy-paste, shell history expansion, line wrapping, or URL decoding (e.g. missing padding making the segment shift).

Common situations: Copying tokens through chat/tickets that clip long strings; storing tokens in YAML with folding that drops characters; double-encoding issues when tokens travel through URLs or base64 wrappers.

Understand the failure class

Related errors


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/4f0957f666f3a342. Report an issue: GitHub.