derailed/k9s · error

unable to find controller for replicaset: %s

Error message

unable to find controller for replicaset: %s

What it means

controllerInfo walks a ReplicaSet's ownerReferences for an entry with controller=true to identify its managing controller (normally a Deployment) — required to build rollback info. ReplicaSets created standalone, or orphaned by deleting their Deployment with --cascade=orphan, have no controller ref, so the lookup fails and names the RS.

Source

Thrown at internal/dao/rs.go:84

		return 0, errors.New("revision conversion failed")
	}

	return int64(vers), nil
}

func controllerInfo(rs *appsv1.ReplicaSet) (name, kind, group string, err error) {
	for _, ref := range rs.OwnerReferences {
		if ref.Controller == nil {
			continue
		}
		group, tokens := ref.APIVersion, strings.Split(ref.APIVersion, "/")
		if len(tokens) == 2 {
			group = tokens[0]
		}
		return ref.Name, ref.Kind, group, nil
	}

	return "", "", "", fmt.Errorf("unable to find controller for replicaset: %s", rs.Name)
}

// Rollback reverses the last deployment.
func (r *ReplicaSet) Rollback(fqn string) error {
	rs, err := r.Load(r.Factory, fqn)
	if err != nil {
		return err
	}

	version, err := getRSRevision(rs)
	if err != nil {
		return err
	}
	name, kind, apiGroup, err := controllerInfo(rs)
	if err != nil {
		return err
	}
	dial, err := r.Client().Dial()

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Roll back via the owning Deployment's history instead: kubectl rollout undo deployment/<d>
  2. If the Deployment is gone, recreate it or restore ownership by re-adding ownerReferences pointing at a valid controller UID
  3. Inspect ownership first: kubectl get rs <rs> -o jsonpath='{.metadata.ownerReferences}'

Example fix

# before
k9s rollback on orphaned replicaset my-rs  (rejected)

# after
# check ownership
kubectl get rs my-rs -o jsonpath='{.metadata.ownerReferences}'
# roll back the controller that owns it
kubectl rollout undo deployment/my-deploy
Defensive patterns

Strategy: type-guard

Validate before calling

rs, err := r.Load(f, fqn)
if err != nil { return err }
if _, _, _, cerr := controllerInfo(rs); cerr != nil {
    return fmt.Errorf("rs %s is orphaned; roll back via its deployment", rs.Name)
}

Type guard

func hasController(rs *appsv1.ReplicaSet) bool {
    for _, ref := range rs.OwnerReferences {
        if ref.Controller != nil && *ref.Controller {
            return true
        }
    }
    return false
}

Try / catch

if err := rsDAO.Rollback(fqn); err != nil {
    if strings.Contains(err.Error(), "unable to find controller for replicaset") {
        // no controller: fall back to manual pod-template rollback or recreate deployment
    }
}

Prevention

When it happens

Trigger: Calling ReplicaSet.Rollback on an RS whose ownerReferences are empty or lack a controller=true entry.

Common situations: kubectl delete deployment <d> --cascade=orphan during migration leaving live RSs; RSs created directly by manifests or older tooling; ownership stripped by webhook mutations.

Related errors


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/08b104a2b43e8a7e. Report an issue: GitHub.