kubesphere/kubesphere · error

expect *v1.Pod, got %v

Error message

expect *v1.Pod, got %v

What it means

The pod quota evaluator's type-assertion helper toExternalPodOrError requires a *corev1.Pod. Any other runtime.Object fails the type switch and yields this error. Constraints, podMatchesScopeFunc, and PodUsageFunc all rely on it, so a wrong-typed object at any of those entry points produces this message.

Source

Thrown at kube/pkg/quota/v1/evaluator/core/pods.go:293

			result[maskResourceWithPrefix(resource, corev1.DefaultResourceRequestsPrefix)] = request
		}
		// for extended resources
		if helper.IsExtendedResourceName(resource) {
			// only quota objects in format of "requests.resourceName" is allowed for extended resource.
			result[maskResourceWithPrefix(resource, corev1.DefaultResourceRequestsPrefix)] = request
		}
	}

	return result
}

func toExternalPodOrError(obj runtime.Object) (*corev1.Pod, error) {
	var pod *corev1.Pod
	switch t := obj.(type) {
	case *corev1.Pod:
		pod = t
	default:
		return nil, fmt.Errorf("expect *v1.Pod, got %v", t)
	}
	return pod, nil
}

// podMatchesScopeFunc is a function that knows how to evaluate if a pod matches a scope
func podMatchesScopeFunc(selector corev1.ScopedResourceSelectorRequirement, object runtime.Object) (bool, error) {
	pod, err := toExternalPodOrError(object)
	if err != nil {
		return false, err
	}
	switch selector.ScopeName {
	case corev1.ResourceQuotaScopeTerminating:
		return isTerminating(pod), nil
	case corev1.ResourceQuotaScopeNotTerminating:
		return !isTerminating(pod), nil
	case corev1.ResourceQuotaScopeBestEffort:
		return isBestEffort(pod), nil
	case corev1.ResourceQuotaScopeNotBestEffort:

View on GitHub (pinned to 04a29b5c60)

Solutions

  1. Convert the object to *corev1.Pod (scheme.Convert or the evaluator's toExternalPod helper) before calling quota evaluation APIs.
  2. Verify the informer/handler feeding the evaluator is watching pods and delivering typed *corev1.Pod objects.
  3. In tests, use typed corev1.Pod fixtures instead of generic runtime.Objects.

Example fix

// before
matches, err := evaluator.MatchingScopes(internalPod, selectors)
// after
pod := &corev1.Pod{}
if err := scheme.Convert(internalPod, pod, nil); err != nil { return err }
matches, err := evaluator.MatchingScopes(pod, selectors)
Defensive patterns

Strategy: type-guard

Validate before calling

if obj == nil { return fmt.Errorf("nil object passed to pod quota evaluator") }
pod, ok := obj.(*corev1.Pod)
if !ok { return fmt.Errorf("not a *corev1.Pod: %T", obj) }

Type guard

func isExternalPod(obj runtime.Object) (*corev1.Pod, bool) {
	pod, ok := obj.(*corev1.Pod)
	return pod, ok
}

Try / catch

if err := evaluator.Constraints(resources, obj); err != nil {
	if strings.Contains(err.Error(), "expect *v1.Pod") {
		// convert the object to *corev1.Pod and retry
	}
	return err
}

Prevention

When it happens

Trigger: Passing a runtime.Object that is not *corev1.Pod (internal v1.Pod from another package, nil object, or another resource entirely) into podEvaluator Constraints/MatchingScopes/Usage or podMatchesScopeFunc.

Common situations: Custom quota/admission plugins handling unconverted internal objects; tests reusing fixtures of the wrong type; refactored code paths that forgot the internal-to-external conversion step before quota evaluation.

Related errors


AI-assisted analysis of kubesphere/kubesphere@04a29b5c60 (2026-09-03). Data as JSON: /api/errors/59280f7c0c69030b. Report an issue: GitHub.