GoogleContainerTools/skaffold · error

no receiver was registered

Error message

no receiver was registered

What it means

podWatcher.Start requires at least one receiver registered before it begins watching pods. Calling Start with zero registered receivers returns this error immediately, because watch events would have nowhere to be delivered.

Source

Thrown at pkg/skaffold/kubernetes/watcher.go:72

		receivers:   make(map[chan<- PodEvent]bool),
	}
}

func (w *podWatcher) Register(receiver chan<- PodEvent) {
	w.receiverLock.Lock()
	w.receivers[receiver] = true
	w.receiverLock.Unlock()
}

func (w *podWatcher) Deregister(receiver chan<- PodEvent) {
	w.receiverLock.Lock()
	w.receivers[receiver] = false
	w.receiverLock.Unlock()
}

func (w *podWatcher) Start(ctx context.Context, kubeContext string, namespaces []string) (func(), error) {
	if len(w.receivers) == 0 {
		return func() {}, errors.New("no receiver was registered")
	}

	var watchers []watch.Interface
	stopWatchers := func() {
		for _, w := range watchers {
			w.Stop()
		}
	}

	kubeclient, err := client.Client(kubeContext)
	if err != nil {
		return func() {}, fmt.Errorf("getting k8s client: %w", err)
	}

	var forever int64 = 3600 * 24 * 365 * 100

	for _, ns := range namespaces {
		watcher, err := kubeclient.CoreV1().Pods(ns).Watch(context.Background(), metav1.ListOptions{

View on GitHub (pinned to a1189de023)

Solutions

  1. Register at least one receiver with podWatcher.AddReceiver before calling Start
  2. Reorder startup so receiver registration happens before the watcher starts
  3. Guard the call site: only start the watcher when the receiver list is non-empty

Example fix

// before
watcher.Start(ctx, kubeContext, namespaces) // error: no receiver was registered
// after
watcher.AddReceiver(receiver)
watcher.Start(ctx, kubeContext, namespaces)
Defensive patterns

Strategy: validation

Validate before calling

if len(watcher.ReceiverCount()) == 0 { return errors.New("refusing to start podWatcher with no receivers") }
if err := watcher.Start(ctx, kubeContext, namespaces); err != nil { return err }

Type guard

func (w *podWatcher) HasReceivers() bool { return len(w.receivers) > 0 }

Try / catch

stop, err := watcher.Start(ctx, kubeContext, ns)
if err != nil {
  if strings.Contains(err.Error(), "no receiver was registered") { return fmt.Errorf("watcher startup ordering bug: %w", err) }
  return err
}
defer stop()

Prevention

When it happens

Trigger: Calling podWatcher.Start(ctx, kubeContext, namespaces) before any call to AddReceiver (or after all receivers were removed).

Common situations: Race in startup code where the watch is started before the status-check receiver is registered; a refactor removing AddReceiver calls; conditional code path that skips receiver registration.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/14373dcb58632aaf. Report an issue: GitHub.