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
- Roll back via the owning Deployment's history instead: kubectl rollout undo deployment/<d>
- If the Deployment is gone, recreate it or restore ownership by re-adding ownerReferences pointing at a valid controller UID
- 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
- Avoid --cascade=orphan deletes unless you plan to adopt the orphans
- Expose rollback actions only on RSs with a controller ownerReference
- Keep Deployment manifests in sync so rollout undo is always available as the primary path
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
- can not rollback current replica
- revision conversion failed
- unable to set image. This pod is managed by %s. Please set t
- expected Unstructured, but got %T
- did not phase down correctly expecting 0 replicas but got %d
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/08b104a2b43e8a7e.
Report an issue: GitHub.