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
- Convert the object to *corev1.Pod (scheme.Convert or the evaluator's toExternalPod helper) before calling quota evaluation APIs.
- Verify the informer/handler feeding the evaluator is watching pods and delivering typed *corev1.Pod objects.
- 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
- Convert internal types to corev1 external types before quota calls
- Ensure informer handlers deliver typed *corev1.Pod objects
- Nil-check objects before evaluator entry points
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
- expect *v1.PersistentVolumeClaim, got %v
- expect *v1.Service, got %v
- must specify %s
- error on matching scope %v: %v
- failed to parse and convert selector: %v
AI-assisted analysis of kubesphere/kubesphere@04a29b5c60 (2026-09-03).
Data as JSON: /api/errors/59280f7c0c69030b.
Report an issue: GitHub.