rancher/rancher · error

secret [%s] must be of type [%s] or [%s] or [%s]

Error message

secret [%s] must be of type [%s] or [%s] or [%s]

What it means

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.

Source

Thrown at pkg/capr/planner/registry.go:85

				registryConfig.TLS.KeyFile = file.Path
				files = append(files, file)
			}
		}

		if len(config.CABundle) > 0 {
			file := toFile(controlPlane, fmt.Sprintf("tls/registries/%s/ca.crt", registryName), config.CABundle)
			registryConfig.TLS.CAFile = file.Path
			files = append(files, file)
		}

		if config.AuthConfigSecretName != "" {
			secret, err := p.secretCache.Get(controlPlane.Namespace, config.AuthConfigSecretName)
			if err != nil {
				return data, err
			}

			if secret.Type != rkev1.AuthConfigSecretType && secret.Type != corev1.SecretTypeBasicAuth && secret.Type != corev1.SecretTypeDockerConfigJson {
				return data, fmt.Errorf("secret [%s] must be of type [%s] or [%s] or [%s]",
					config.AuthConfigSecretName, rkev1.AuthConfigSecretType, corev1.SecretTypeBasicAuth, corev1.SecretTypeDockerConfigJson)
			}

			if secret.Data == nil {
				return data, fmt.Errorf("secret [%s] has nil data", config.AuthConfigSecretName)
			}

			username := string(secret.Data[rkev1.UsernameAuthConfigSecretKey])
			password := string(secret.Data[rkev1.PasswordAuthConfigSecretKey])
			// we need to re-encode the auth block for containerd to leverage it properly.
			// The secret cache automatically decodes data values for us to make them easier to work with,
			// but containerd will refuse to work with an unencoded auth block.
			auth := base64.StdEncoding.EncodeToString(secret.Data[rkev1.AuthAuthConfigSecretKey])
			identityToken := string(secret.Data[rkev1.IdentityTokenAuthConfigSecretKey])

			// need to pull out the username, password, auth, from the .dockerconfigjson key
			if secret.Type == corev1.SecretTypeDockerConfigJson {
				username, password, auth, err = cluster.UnwrapDockerConfigJson(registryName, secret.Data)

View on GitHub (pinned to 932558d4e6)

Solutions

  1. 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>
  2. 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>
  3. Or patch the type in place: kubectl -n <cluster-ns> patch secret reg-auth -p '{"type":"kubernetes.io/basic-auth"}'
  4. Verify the value of authConfigSecretName in the control plane's rkeConfig matches the intended secret in the same namespace as the RKEControlPlane object

Example fix

# before
apiVersion: v1
kind: Secret
metadata:
  name: reg-auth
  namespace: c-m-xxxxx
# no type -> Opaque -> error 620

# after
type: kubernetes.io/basic-auth
stringData:
  username: myuser
  password: mypass
Defensive patterns

Strategy: validation

Validate before calling

// Before setting authConfigSecretName, verify the secret type
const (
	TypeAuthConfig = "rke.cattle.io/auth-config"
	TypeBasicAuth  = "kubernetes.io/basic-auth"
	TypeDockerJSON = "kubernetes.io/dockerconfigjson"
)

func validRegistryAuthSecret(s *corev1.Secret) bool {
	if s == nil {
		return false
	}
	return s.Type == TypeAuthConfig || s.Type == TypeBasicAuth || s.Type == TypeDockerJSON
}

// secret, err := secretCache.Get(cp.Namespace, cfg.AuthConfigSecretName)
// if err == nil && !validRegistryAuthSecret(secret) { /* fix secret before applying rkeConfig */ }

Type guard

func isRegistryAuthSecret(s *corev1.Secret) bool {
	switch s.GetType() {
	case "rke.cattle.io/auth-config", "kubernetes.io/basic-auth", "kubernetes.io/dockerconfigjson":
		return true
	}
	return false
}

Try / catch

err := reconcileRegistries(...) // planner call
if err != nil {
	if strings.Contains(err.Error(), "must be of type") {
		// secret-type problem: recreate the secret with basic-auth/dockerconfigjson type, then requeue
	}
	return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of rancher/rancher@932558d4e6 (2026-08-16). Data as JSON: /api/errors/6dbe47cd7118327d. Report an issue: GitHub.