{"record":{"id":"4f0957f666f3a342","repo":"k3s-io/k3s","slug":"invalid-token-ca-hash-length","errorCode":null,"errorMessage":"invalid token CA hash length","messagePattern":"invalid token CA hash length","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/clientaccess/token.go","lineNumber":239,"sourceCode":"\tif !strings.HasPrefix(token, tokenPrefix) {\n\t\t_, err := kubeadm.NewBootstrapTokenString(token)\n\t\tif err != nil {\n\t\t\ttoken = tokenPrefix + \":::\" + token\n\t\t} else {\n\t\t\ttoken = tokenPrefix + \"::\" + token\n\t\t}\n\t}\n\n\t// Strip off the prefix.\n\ttoken = token[len(tokenPrefix):]\n\n\t// Split into CA hash and creds.\n\tparts := strings.SplitN(token, \"::\", 2)\n\ttoken = parts[0]\n\tif len(parts) > 1 {\n\t\thashLen := len(parts[0])\n\t\tif hashLen > 0 && hashLen != caHashLength {\n\t\t\treturn nil, errors.New(\"invalid token CA hash length\")\n\t\t}\n\t\tinfo.caHash = parts[0]\n\t\ttoken = parts[1]\n\t}\n\n\t// Try to parse creds as bootstrap token string; fall back to basic auth.\n\t// If neither works, error.\n\tbts, err := kubeadm.NewBootstrapTokenString(token)\n\tif err != nil {\n\t\tparts = strings.SplitN(token, \":\", 2)\n\t\tif len(parts) != 2 || len(parts[1]) == 0 {\n\t\t\treturn nil, errors.New(\"invalid token format\")\n\t\t}\n\t\tinfo.Username = parts[0]\n\t\tinfo.Password = parts[1]\n\t} else {\n\t\tinfo.BootstrapTokenString = bts\n\t}","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/clientaccess/token.go#L221-L257","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before (hash truncated to 8 chars)\nK10deadbeef::abcdef.0123456789abcdef\n\n# after (full 64-char sha256 hex hash)\nK10e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855::abcdef.0123456789abcdef","handlingStrategy":"validation","validationCode":"// k3s node token: K10[<64-hex sha256 CA hash>]::<bootstrap-token|user:pass>\nvar k3sTokenRe = regexp.MustCompile(`^K10([0-9a-f]{64})?::([^:]+|[^:]{6}\\.[a-z0-9]{16}|[^:]+:[^:]+)$`)\nif !k3sTokenRe.MatchString(token) {\n    return fmt.Errorf(\"token failed pre-validation; expected hash segment of exactly 64 hex chars\")\n}","typeGuard":"func validK3sTokenHash(token string) bool {\n    s := strings.TrimPrefix(token, \"K10\")\n    hash := strings.SplitN(s, \"::\", 2)[0]\n    return hash == \"\" || len(hash) == 64\n}","tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"invalid token CA hash length\") {\n        // token was clipped or mangled in transit; re-fetch from source of truth\n        token = fetchFreshToken()\n    }\n}","preventionTips":["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"],"tags":["token","validation","format","clientaccess"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}