{"record":{"id":"6dbe47cd7118327d","repo":"rancher/rancher","slug":"secret-s-must-be-of-type-s-or-s-or-s","errorCode":null,"errorMessage":"secret [%s] must be of type [%s] or [%s] or [%s]","messagePattern":"secret \\[(.+?)\\] must be of type \\[(.+?)\\] or \\[(.+?)\\] or \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/capr/planner/registry.go","lineNumber":85,"sourceCode":"\t\t\t\tregistryConfig.TLS.KeyFile = file.Path\n\t\t\t\tfiles = append(files, file)\n\t\t\t}\n\t\t}\n\n\t\tif len(config.CABundle) > 0 {\n\t\t\tfile := toFile(controlPlane, fmt.Sprintf(\"tls/registries/%s/ca.crt\", registryName), config.CABundle)\n\t\t\tregistryConfig.TLS.CAFile = file.Path\n\t\t\tfiles = append(files, file)\n\t\t}\n\n\t\tif config.AuthConfigSecretName != \"\" {\n\t\t\tsecret, err := p.secretCache.Get(controlPlane.Namespace, config.AuthConfigSecretName)\n\t\t\tif err != nil {\n\t\t\t\treturn data, err\n\t\t\t}\n\n\t\t\tif secret.Type != rkev1.AuthConfigSecretType && secret.Type != corev1.SecretTypeBasicAuth && secret.Type != corev1.SecretTypeDockerConfigJson {\n\t\t\t\treturn data, fmt.Errorf(\"secret [%s] must be of type [%s] or [%s] or [%s]\",\n\t\t\t\t\tconfig.AuthConfigSecretName, rkev1.AuthConfigSecretType, corev1.SecretTypeBasicAuth, corev1.SecretTypeDockerConfigJson)\n\t\t\t}\n\n\t\t\tif secret.Data == nil {\n\t\t\t\treturn data, fmt.Errorf(\"secret [%s] has nil data\", config.AuthConfigSecretName)\n\t\t\t}\n\n\t\t\tusername := string(secret.Data[rkev1.UsernameAuthConfigSecretKey])\n\t\t\tpassword := string(secret.Data[rkev1.PasswordAuthConfigSecretKey])\n\t\t\t// we need to re-encode the auth block for containerd to leverage it properly.\n\t\t\t// The secret cache automatically decodes data values for us to make them easier to work with,\n\t\t\t// but containerd will refuse to work with an unencoded auth block.\n\t\t\tauth := base64.StdEncoding.EncodeToString(secret.Data[rkev1.AuthAuthConfigSecretKey])\n\t\t\tidentityToken := string(secret.Data[rkev1.IdentityTokenAuthConfigSecretKey])\n\n\t\t\t// need to pull out the username, password, auth, from the .dockerconfigjson key\n\t\t\tif secret.Type == corev1.SecretTypeDockerConfigJson {\n\t\t\t\tusername, password, auth, err = cluster.UnwrapDockerConfigJson(registryName, secret.Data)","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/rancher/rancher/blob/932558d4e68565aff2d2f36e89ec4a391b06e7c5/pkg/capr/planner/registry.go#L67-L103","documentation":"Thrown by the RKE2/K3s cluster planner while generating containerd registry configuration. A registry entry in RKEControlPlane.spec.rkeConfig.registries points at a secret via authConfigSecretName, and the secret was found but its .type is not one of the three accepted types: rke.cattle.io/auth-config (rkev1.AuthConfigSecretType), kubernetes.io/basic-auth, or kubernetes.io/dockerconfigjson. The planner refuses to build the auth block from any other secret type, so control-plane provisioning stops.","triggerScenarios":"Setting spec.rkeConfig.registries.<name>.authConfigSecretName (or the mirrors section) on an RKEControlPlane to a secret created without an explicit type. Example: kubectl create secret generic reg-auth --from-literal=username=... --from-literal=password=... produces type Opaque, which fails this check during plan generation.","commonSituations":"Users create the registry auth secret with 'create secret generic' (defaults to Opaque) instead of basic-auth or docker-registry; a secret was recreated after a rename and lost its --type flag; docs or automation scripts that predate this type check; the name resolves to a different, unrelated secret in the control-plane namespace.","solutions":["Recreate the secret with an accepted type: kubectl -n <cluster-ns> create secret generic reg-auth --type=kubernetes.io/basic-auth --from-literal=username=<user> --from-literal=password=<pass>","Or use a docker-config secret: kubectl -n <cluster-ns> create secret docker-registry reg-auth --docker-server=<registry> --docker-username=<user> --docker-password=<pass>","Or patch the type in place: kubectl -n <cluster-ns> patch secret reg-auth -p '{\"type\":\"kubernetes.io/basic-auth\"}'","Verify the value of authConfigSecretName in the control plane's rkeConfig matches the intended secret in the same namespace as the RKEControlPlane object"],"exampleFix":"# before\napiVersion: v1\nkind: Secret\nmetadata:\n  name: reg-auth\n  namespace: c-m-xxxxx\n# no type -> Opaque -> error 620\n\n# after\ntype: kubernetes.io/basic-auth\nstringData:\n  username: myuser\n  password: mypass","handlingStrategy":"validation","validationCode":"// Before setting authConfigSecretName, verify the secret type\nconst (\n\tTypeAuthConfig = \"rke.cattle.io/auth-config\"\n\tTypeBasicAuth  = \"kubernetes.io/basic-auth\"\n\tTypeDockerJSON = \"kubernetes.io/dockerconfigjson\"\n)\n\nfunc validRegistryAuthSecret(s *corev1.Secret) bool {\n\tif s == nil {\n\t\treturn false\n\t}\n\treturn s.Type == TypeAuthConfig || s.Type == TypeBasicAuth || s.Type == TypeDockerJSON\n}\n\n// secret, err := secretCache.Get(cp.Namespace, cfg.AuthConfigSecretName)\n// if err == nil && !validRegistryAuthSecret(secret) { /* fix secret before applying rkeConfig */ }","typeGuard":"func isRegistryAuthSecret(s *corev1.Secret) bool {\n\tswitch s.GetType() {\n\tcase \"rke.cattle.io/auth-config\", \"kubernetes.io/basic-auth\", \"kubernetes.io/dockerconfigjson\":\n\t\treturn true\n\t}\n\treturn false\n}","tryCatchPattern":"err := reconcileRegistries(...) // planner call\nif err != nil {\n\tif strings.Contains(err.Error(), \"must be of type\") {\n\t\t// secret-type problem: recreate the secret with basic-auth/dockerconfigjson type, then requeue\n\t}\n\treturn err\n}","preventionTips":["Always create registry auth secrets with kubectl create secret docker-registry or --type=kubernetes.io/basic-auth, never bare generic secrets","Add admission-time policy (Kyverno/OPA) requiring one of the three accepted types for secrets referenced as registry auth","Add a lint step in CI for RKEControlPlane manifests that resolves authConfigSecretName and asserts the secret type"],"tags":["kubernetes","rke2","secrets","registry","containerd","auth"],"backgroundTag":null,"analyzedSha":"932558d4e68565aff2d2f36e89ec4a391b06e7c5","analyzedAt":"2026-08-16T04:37:02.125Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}