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
- 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
- Check length: the hash segment between 'K10' and '::' must be exactly 64 hex characters
- 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
- Transport tokens via files/secrets, never chat/email
- Validate length (64-hex hash segment) before first use
- Compare token checksums between issuer and consumer when debugging join failures
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- invalid token format
- token must not be empty
- only https:// URLs are supported, invalid scheme:
- invalid output format: {cfg.Output}
- Failed checking netMode
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/4f0957f666f3a342.
Report an issue: GitHub.