{"record":{"id":"ae83736f0a519130","repo":"derailed/k9s","slug":"expecting-service-resource","errorCode":null,"errorMessage":"expecting Service resource","messagePattern":"expecting Service resource","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/sts.go","lineNumber":109,"sourceCode":"func (s *StatefulSet) Pod(fqn string) (string, error) {\n\tsts, err := s.getStatefulSet(fqn)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn podFromSelector(s.Factory, sts.Namespace, sts.Spec.Selector.MatchLabels)\n}\n\nfunc (s *StatefulSet) getStatefulSet(fqn string) (*appsv1.StatefulSet, error) {\n\to, err := s.getFactory().Get(s.gvr, fqn, true, labels.Everything())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar sts appsv1.StatefulSet\n\terr = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &sts)\n\tif err != nil {\n\t\treturn nil, errors.New(\"expecting Service resource\")\n\t}\n\n\treturn &sts, nil\n}\n\n// ScanSA scans for serviceaccount refs.\nfunc (s *StatefulSet) ScanSA(_ context.Context, fqn string, wait bool) (Refs, error) {\n\tns, n := client.Namespaced(fqn)\n\too, err := s.getFactory().List(s.gvr, ns, wait, labels.Everything())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trefs := make(Refs, 0, len(oo))\n\tfor _, o := range oo {\n\t\tvar sts appsv1.StatefulSet\n\t\terr = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &sts)\n\t\tif err != nil {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/sts.go#L91-L127","documentation":"StatefulSet.getStatefulSet converts the fetched unstructured object to appsv1.StatefulSet; on failure it returns 'expecting Service resource'. The message is a copy-paste from the Service DAO: the code is StatefulSet-specific and only the text is wrong. Semantics are identical to the StatefulSet conversion failure: the object's shape did not match appsv1.StatefulSet.","triggerScenarios":"The object returned by s.getFactory().Get(s.gvr, fqn, ...) is not convertible to appsv1.StatefulSet — s.gvr misconfigured (pointing at a non-sts resource), apiVersion drift, or webhook-mutated fields that the typed converter rejects.","commonSituations":"Initializing the DAO with a GVR other than client.StsGVR; cluster/apiVersion upgrades; debugging confused by the wrong 'Service' wording pointing devs at the Service code path.","solutions":["Treat it as a StatefulSet conversion failure (the message text is wrong); verify the GVR passed to Init is client.StsGVR.","Confirm apiVersion apps/v1 and a valid StatefulSet payload via kubectl get sts -o yaml.","Correct the message locally or wrap the underlying conversion error to avoid the misleading text."],"exampleFix":"// before (misleading copy-paste in internal/dao/sts.go getStatefulSet)\nif err != nil { return nil, errors.New(\"expecting Service resource\") }\n// after\nif err != nil { return nil, fmt.Errorf(\"expecting StatefulSet resource: %w\", err) }","handlingStrategy":"type-guard","validationCode":"if s.gvr != client.StsGVR.String() { // guard DAO misuse\n    return nil, fmt.Errorf(\"statefulset DAO initialized with wrong gvr: %s\", s.gvr)\n}","typeGuard":"func isStatefulSet(o runtime.Object) bool {\n    u, ok := o.(*unstructured.Unstructured)\n    return ok && u.GetKind() == \"StatefulSet\"\n}","tryCatchPattern":null,"preventionTips":["Remember the 'Service' wording is a copy-paste bug; diagnose as StatefulSet conversion.","Always Init the DAO with client.StsGVR.","Validate apiVersion apps/v1 before conversion."],"tags":["go","kubernetes","statefulset","copy-paste-bug","conversion"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}