Inconsistent requeue strategy for missing dependency-like references
Describe the bug
When a controller is waiting for a dependency-like resource to appear (source object, valuesFrom ConfigMap/Secret, substituteFrom ConfigMap/Secret), the requeue strategy is inconsistent with how dependsOn and "source exists but not ready" are handled.
Both helm-controller and kustomize-controller use --requeue-dependency for dependsOn not-ready and source-exists-but-artifact-missing, but use different (worse) strategies for other "waiting for a resource" scenarios.
helm-controller
| Scenario | Requeue strategy |
|---|---|
dependsOn not ready |
--requeue-dependency |
| Source exists but not ready | --requeue-dependency |
| Artifact fetch file not found | --requeue-dependency |
Source object not found (chartRef) |
exponential backoff |
valuesFrom not found |
exponential backoff |
Source object not found (helmrelease_controller.go#L288-L290):
msg := fmt.Sprintf("could not get Source object: %s", err.Error())
conditions.MarkFalse(obj, meta.ReadyCondition, v2.ArtifactFailedReason, "%s", msg)
return ctrl.Result{}, errvaluesFrom not found (helmrelease_controller.go#L318-L320):
conditions.MarkFalse(obj, meta.ReadyCondition, "ValuesError", "%s", err)
r.Eventf(obj, corev1.EventTypeWarning, "ValuesError", err.Error())
return ctrl.Result{}, errkustomize-controller
| Scenario | Requeue strategy |
|---|---|
dependsOn not ready |
--requeue-dependency |
| Source artifact nil | --requeue-dependency |
| Artifact fetch file not found | --requeue-dependency |
| Source object not found | retryInterval |
substituteFrom not found |
retryInterval |
Source object not found (kustomization_controller.go#L214-L217):
if apierrors.IsNotFound(err) {
msg := fmt.Sprintf("Source '%s' not found", obj.Spec.SourceRef.String())
log.Info(msg)
return ctrl.Result{RequeueAfter: obj.GetRetryInterval()}, nil
}substituteFrom not found — caught as a general reconcile error (kustomization_controller.go#L289-L297):
if reconcileErr != nil {
log.Error(reconcileErr, fmt.Sprintf("Reconciliation failed after %s, next try in %s",
time.Since(reconcileStart).String(),
obj.GetRetryInterval().String()),
"revision",
revision)
r.event(obj, revision, originRevision, eventv1.EventSeverityError,
reconcileErr.Error(), nil)
return ctrl.Result{RequeueAfter: obj.GetRetryInterval()}, nil
}Expected behavior
All "waiting for a dependency-like resource to exist" scenarios should requeue with --requeue-dependency, consistent with dependsOn not-ready and source-not-ready handling.
Use case
This matters when resources are deployed together in the same sync path (e.g. via a ResourceSet). A HelmRelease may reference a valuesFrom ConfigMap generated by a Kustomize configMapGenerator, or a chartRef OCIRepository — these may not exist yet when the HelmRelease is first reconciled. Exponential backoff (or the full retry/reconcile interval) delays the eventual reconciliation unnecessarily compared to the short --requeue-dependency interval.
Source: fluxcd/flux2