kubernetes/kubernetes · warning

nil EndpointSlice passed to serviceControllerKey()

Error message

nil EndpointSlice passed to serviceControllerKey()

What it means

Emitted by endpointsControllerKey when called with a nil EndpointSlice pointer. The function derives a namespace/name key from the EndpointSlice to queue the corresponding Endpoints resource for reconciliation. A nil slice has no namespace or labels, so the key cannot be derived.

Source

Thrown at pkg/controller/endpointslicemirroring/utils.go:218

	// state is unrecorded.
	tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
	if !ok {
		utilruntime.HandleError(fmt.Errorf("couldn't get object from tombstone %#v", obj))
		return nil
	}
	endpointSlice, ok := tombstone.Obj.(*discovery.EndpointSlice)
	if !ok {
		utilruntime.HandleError(fmt.Errorf("tombstone contained object that is not an EndpointSlice resource: %#v", obj))
		return nil
	}
	return endpointSlice
}

// endpointsControllerKey returns a controller key for an Endpoints resource but
// derived from an EndpointSlice.
func endpointsControllerKey(endpointSlice *discovery.EndpointSlice) (string, error) {
	if endpointSlice == nil {
		return "", fmt.Errorf("nil EndpointSlice passed to serviceControllerKey()")
	}
	serviceName, ok := endpointSlice.Labels[discovery.LabelServiceName]
	if !ok || serviceName == "" {
		return "", fmt.Errorf("EndpointSlice missing %s label", discovery.LabelServiceName)
	}
	return fmt.Sprintf("%s/%s", endpointSlice.Namespace, serviceName), nil
}

// skipMirror return true if the LabelSkipMirror label has been set to
// "true".
func skipMirror(labels map[string]string) bool {
	skipMirror, _ := labels[discovery.LabelSkipMirror]
	return skipMirror == "true"
}

// hasLeaderElection returns true if the LeaderElectionRecordAnnotationKey is
// set as an annotation.
func hasLeaderElection(annotations map[string]string) bool {

View on GitHub (pinned to 94c1367642)

Solutions

  1. Ensure callers check endpointSlice != nil before calling endpointsControllerKey.
  2. In tests, always pass a valid *discovery.EndpointSlice.
  3. If seen in production, trace the call stack to find which code path skipped the nil guard.
  4. The controller already handles this gracefully by logging and returning.

Example fix

// before
key, err := endpointsControllerKey(nil)

// after
if endpointSlice == nil {
    return
}
key, err := endpointsControllerKey(endpointSlice)
Defensive patterns

Strategy: validation

Validate before calling

if endpointSlice == nil {
    // skip calling endpointsControllerKey
    return
}

Type guard

func isNonNilEndpointSlice(slice *discovery.EndpointSlice) bool {
    return slice != nil
}

Prevention

When it happens

Trigger: queueEndpointsForEndpointSlice is called with a nil *discovery.EndpointSlice. This should not happen in normal flow since callers check for nil before calling, but could occur if a code path or test invokes endpointsControllerKey directly with nil.

Common situations: Direct unit tests of endpointsControllerKey passing nil. A logic bug where a nil check is skipped before calling the function. Extremely unlikely in production given the controller's nil guards upstream.

Related errors


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