kubernetes/kubernetes · warning

can't adopt ReplicaSet %v/%v (%v): %v

Error message

can't adopt ReplicaSet %v/%v (%v): %v

What it means

Returned by ReplicaSetControllerRefManager.AdoptReplicaSet when CanAdopt fails before the owner-reference patch is applied. Identical mechanism to Pod adoption: CanAdopt (often RecheckDeletionTimestamp) re-checks the parent and rejects adoption if the parent is being deleted or the re-GET errors. Bubbles up via ClaimReplicaSets as part of an aggregated error.

Source

Thrown at pkg/controller/controller_ref_manager.go:350

	for _, rs := range sets {
		ok, err := m.ClaimObject(ctx, rs, match, adopt, release)
		if err != nil {
			errlist = append(errlist, err)
			continue
		}
		if ok {
			claimed = append(claimed, rs)
		}
	}
	return claimed, utilerrors.NewAggregate(errlist)
}

// AdoptReplicaSet sends a patch to take control of the ReplicaSet. It returns
// the error if the patching fails.
func (m *ReplicaSetControllerRefManager) AdoptReplicaSet(ctx context.Context, rs *apps.ReplicaSet) error {
	if err := m.CanAdopt(ctx); err != nil {
		return fmt.Errorf("can't adopt ReplicaSet %v/%v (%v): %v", rs.Namespace, rs.Name, rs.UID, err)
	}
	// Note that ValidateOwnerReferences() will reject this patch if another
	// OwnerReference exists with controller=true.
	patchBytes, err := ownerRefControllerPatch(m.Controller, m.controllerKind, rs.UID)
	if err != nil {
		return err
	}
	return m.rsControl.PatchReplicaSet(ctx, rs.Namespace, rs.Name, patchBytes)
}

// ReleaseReplicaSet sends a patch to free the ReplicaSet from the control of the Deployment controller.
// It returns the error if the patching fails. 404 and 422 errors are ignored.
func (m *ReplicaSetControllerRefManager) ReleaseReplicaSet(ctx context.Context, replicaSet *apps.ReplicaSet) error {
	logger := klog.FromContext(ctx)
	logger.V(2).Info("Patching ReplicaSet to remove its controllerRef", "replicaSet", klog.KObj(replicaSet), "gvk", m.controllerKind, "controller", m.Controller.GetName())
	patchBytes, err := GenerateDeleteOwnerRefStrategicMergeBytes(replicaSet.UID, []types.UID{m.Controller.GetUID()})
	if err != nil {
		return err

View on GitHub (pinned to 94c1367642)

Solutions

  1. During parent Deployment deletion this is expected; the ReplicaSet controller will release rather than adopt.
  2. If the parent flaps (rapid delete/recreate), stabilize the parent lifecycle.
  3. Verify apiserver health if GET errors dominate.
  4. Inspect the wrapped error to classify deletion vs network.

Example fix

// before
if err := m.CanAdopt(ctx); err != nil {
    return fmt.Errorf("can't adopt ReplicaSet %v/%v (%v): %v", rs.Namespace, rs.Name, rs.UID, err)
}
// after: log-and-skip during parent teardown to avoid noisy aggregated errors
if err := m.CanAdopt(ctx); err != nil {
    klog.FromContext(ctx).V(3).Info("Skipping ReplicaSet adoption", "rs", klog.KObj(rs), "reason", err)
    return fmt.Errorf("can't adopt ReplicaSet %v/%v (%v): %v", rs.Namespace, rs.Name, rs.UID, err)
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check parent Deployment is stable before adopting ReplicaSets
parent, err := deploymentGetter.Get(ctx)
if err != nil || parent.GetDeletionTimestamp() != nil {
    return nil
}

Try / catch

claimed, err := m.ClaimReplicaSets(ctx, sets)
if err != nil {
    if isParentDeletionError(err) { return claimed, nil }
    return claimed, err
}

Prevention

When it happens

Trigger: ClaimReplicaSets -> ClaimObject -> adopt -> AdoptReplicaSet -> CanAdopt(ctx) errors. Typical: the parent Deployment is being deleted (DeletionTimestamp set) when the ReplicaSet controller tries to adopt orphaned ReplicaSets; or the parent GET fails.

Common situations: Deployment deletion in progress; parent (Deployment) UID mismatch because it was recreated; apiserver GET transient failure; multiple controllers (e.g., old and new deployment controller) racing.

Related errors


AI-assisted analysis of kubernetes/kubernetes@94c1367642 (2026-08-08). Data as JSON: /api/errors/a74404204c04177a. Report an issue: GitHub.