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

  1. Register indexers before starting the shared informer factory (before WaitForCacheSync / Run).
  2. Ensure only one ControllerV2 is constructed per job informer, or use a fresh SharedInformerFactory per controller.
  3. 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

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


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