kubernetes/kubernetes · critical
adding job controller UID indexer: %w
Error message
adding job controller UID indexer: %w
What it means
Returned by NewControllerV2 (or equivalent constructor) when jobInformer.Informer().AddIndexers fails for the jobControllerUIDIndex. The shared informer framework rejects AddIndexers once the informer has already started or when an indexer with the same name is already registered. The CronJob v2 controller relies on this index to look up Jobs by their owner CronJob UID.
Source
Thrown at pkg/controller/cronjob/cronjob_controllerv2.go:148
DeleteFunc: func(obj interface{}) {
jm.enqueueController(obj)
},
})
err := jobInformer.Informer().AddIndexers(cache.Indexers{
jobControllerUIDIndex: func(obj interface{}) ([]string, error) {
job, ok := obj.(*batchv1.Job)
if !ok {
return nil, nil
}
if controllerRef := metav1.GetControllerOf(job); controllerRef != nil {
return []string{string(controllerRef.UID)}, nil
}
return nil, nil
},
})
if err != nil {
return nil, fmt.Errorf("adding job controller UID indexer: %w", err)
}
metrics.Register()
return jm, nil
}
// Run starts the main goroutine responsible for watching and syncing jobs.
func (jm *ControllerV2) Run(ctx context.Context, workers int) {
defer utilruntime.HandleCrash()
// Start event processing pipeline.
jm.broadcaster.StartStructuredLogging(3)
jm.broadcaster.StartRecordingToSink(&corev1client.EventSinkImpl{Interface: jm.kubeClient.CoreV1().Events("")})
defer jm.broadcaster.Shutdown()
logger := klog.FromContext(ctx)
logger.Info("Starting cronjob controller v2")View on GitHub (pinned to 94c1367642)
Solutions
- Register indexers before starting the shared informer factory (before WaitForCacheSync / Run).
- Ensure only one ControllerV2 is constructed per job informer, or use a fresh SharedInformerFactory per controller.
- In tests, call AddIndexers on the informer before informer.Start().
Example fix
// before factory.Start(ctx.Done()) jm, _ := cronjob.NewControllerV2(...) // after jm, _ := cronjob.NewControllerV2(...) // AddIndexers happens here, before Start factory.Start(ctx.Done())
Defensive patterns
Strategy: validation
Validate before calling
// register indexers BEFORE starting the factory
factory := informers.NewSharedInformerFactory(kubeClient, 0)
// construction must occur prior to factory.Start()
jm, err := cronjob.NewControllerV2(ctx, kubeClient, factory.Batch().V1().Jobs(), factory.Batch().V1().CronJobs())
if err != nil { return err }
factory.Start(ctx.Done()) Prevention
- Always AddIndexers before SharedInformerFactory.Start / WaitForCacheSync.
- Construct each controller exactly once per shared informer.
- In tests, assert AddIndexers succeeded before invoking the informer.
When it happens
Trigger: Calling AddIndexers on a job informer that has already been started (Run/RunAsync called), or registering jobControllerUIDIndex twice (e.g., constructing two ControllerV2 instances off one shared informer factory).
Common situations: Constructing the CronJob controller after the shared informer factory has started; registering the same UID index from two controllers sharing one informer; tests that instantiate the informer synchronously then construct the controller.
Related errors
- error getting pods by node name: %w
- adding Pod controller UID indexer: %w
- adding Pod controller UID indexer: %w
- workload indexer is not configured
- podgroup indexer is not configured
AI-assisted analysis of kubernetes/kubernetes@94c1367642 (2026-08-08).
Data as JSON: /api/errors/cae86703f6834d91.
Report an issue: GitHub.