kubernetes/kubernetes · error

adding Pod event handler: %w

Error message

adding Pod event handler: %w

What it means

Returned by NewController when `podInformer.Informer().AddEventHandler(...)` fails (job_controller.go:288-300). Same lifecycle semantics as the Job handler error: handlers must be registered before the informer runs. Failure aborts controller creation.

Source

Thrown at pkg/controller/job/job_controller.go:299

		},
	}); err != nil {
		return nil, fmt.Errorf("adding Job event handler: %w", err)
	}
	jm.jobLister = jobInformer.Lister()
	jm.jobStoreSynced = jobInformer.Informer().HasSynced

	if _, err := podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			jm.addPod(logger, obj)
		},
		UpdateFunc: func(oldObj, newObj interface{}) {
			jm.updatePod(logger, oldObj, newObj)
		},
		DeleteFunc: func(obj interface{}) {
			jm.deletePod(logger, obj, true)
		},
	}); err != nil {
		return nil, fmt.Errorf("adding Pod event handler: %w", err)
	}
	jm.podStore = podInformer.Lister()
	jm.podStoreSynced = podInformer.Informer().HasSynced

	err := controller.AddPodControllerIndexer(podInformer.Informer())
	if err != nil {
		return nil, fmt.Errorf("adding Pod controller UID indexer: %w", err)
	}
	jm.podIndexer = podInformer.Informer().GetIndexer()

	jm.updateStatusHandler = jm.updateJobStatus
	jm.syncHandler = jm.syncJob

	if feature.DefaultFeatureGate.Enabled(features.WorkloadWithJob) {
		if err := jm.addSchedulingInformers(logger, workloadInformer, podGroupInformer); err != nil {
			return nil, err
		}
	}

View on GitHub (pinned to b882c60b40)

Solutions

  1. Register all handlers (Job + Pod + indexer) before `informerFactory.Start`.
  2. Ensure the core/v1 pod informer comes from the same factory passed to NewController.
  3. Inspect the wrapped error for a permissions/listwatch cause.
  4. Confirm kubeClient has list/watch on pods.

Example fix

// before: core factory started, then pod handler added
coreInformerFactory.Start(ctx.Done())
jm, err := job.NewController(... coreInformerFactory.Core().V1().Pods() ...)
// after
jm, err := job.NewController(... coreInformerFactory.Core().V1().Pods() ...)
coreInformerFactory.Start(ctx.Done())
Defensive patterns

Strategy: try-catch

Try / catch

// Same lifecycle guard as the Job handler: register Pod handler before factory.Start.
func buildThenStart(ctx context.Context, coreFactory informers.SharedInformerFactory, build func() error) error {
    if err := build(); err != nil { return err }   // adds Pod handler + indexer
    coreFactory.Start(ctx.Done())
    return nil
}

Prevention

When it happens

Trigger: Pod informer already started; podInformer factory misconfigured; pod listwatch GVR (`""/v1/pods`) unavailable; reusing a stopped shared informer.

Common situations: Embedding the job controller and starting the core shared informer factory too early; apiserver temporarily refusing pod list/watch; client-go version skew.

Related errors


AI-assisted analysis of kubernetes/kubernetes@b882c60b40 (2026-08-07). Data as JSON: /api/errors/a8c647edd1fb6bc5. Report an issue: GitHub.