{"record":{"id":"e73c25d2b70ebe2c","repo":"derailed/k9s","slug":"expected-subjectres-but-got-t","errorCode":null,"errorMessage":"expected SubjectRes, but got %T","messagePattern":"expected SubjectRes, but got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/render/subject.go","lineNumber":41,"sourceCode":"\t\treturn tcell.ColorMediumSpringGreen\n\t}\n}\n\n// Header returns a header row.\nfunc (Subject) Header(string) model1.Header {\n\treturn model1.Header{\n\t\tmodel1.HeaderColumn{Name: \"NAME\"},\n\t\tmodel1.HeaderColumn{Name: \"KIND\"},\n\t\tmodel1.HeaderColumn{Name: \"FIRST LOCATION\"},\n\t\tmodel1.HeaderColumn{Name: \"VALID\", Attrs: model1.Attrs{Wide: true}},\n\t}\n}\n\n// Render renders a K8s resource to screen.\nfunc (s Subject) Render(o any, _ string, r *model1.Row) error {\n\tres, ok := o.(SubjectRes)\n\tif !ok {\n\t\treturn fmt.Errorf(\"expected SubjectRes, but got %T\", s)\n\t}\n\n\tr.ID = res.Name\n\tr.Fields = model1.Fields{\n\t\tres.Name,\n\t\tres.Kind,\n\t\tres.FirstLocation,\n\t\t\"\",\n\t}\n\n\treturn nil\n}\n\n// ----------------------------------------------------------------------------\n// Helpers...\n\n// SubjectRes represents a subject rule.\ntype SubjectRes struct {","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/render/subject.go#L23-L59","documentation":"Subject.Render draws RBAC subject rows and requires a render.SubjectRes value ({Name, Kind, FirstLocation}) built by the subject collector. The comma-ok assertion fails for pointers and any other type, returning this error. Known bug worth knowing: the message formats the renderer receiver s with %T instead of the payload o, so it always reports '*render.Subject' regardless of what was actually passed — do not trust the named type when diagnosing.","triggerScenarios":"Calling Subject{}.Render with &SubjectRes{...} (pointer), unstructured objects, or foreign row types; wiring the subject renderer into views that do not produce SubjectRes rows. The misleading %T makes root-causing harder — reproduce with the actual payload to see the real type.","commonSituations":"Extending the RBAC subject views; plugins listing users/groups/serviceaccounts; refactors switching the subject collector to pointer output.","solutions":["Pass render.SubjectRes by value","Bind the Subject renderer only to subject-producing views","Fix upstream: change fmt.Errorf(\"expected SubjectRes, but got %T\", s) to pass o so the message names the real type","Use comma-ok guards in wrappers and skip mismatches"],"exampleFix":"// before (upstream bug: receiver s hides the real payload type)\nreturn fmt.Errorf(\"expected SubjectRes, but got %T\", s)\n// after\nreturn fmt.Errorf(\"expected SubjectRes, but got %T\", o)","handlingStrategy":"type-guard","validationCode":"// gate before invoking the subject renderer\nif _, ok := o.(render.SubjectRes); !ok {\n\treturn fmt.Errorf(\"subject view requires render.SubjectRes value, got %T\", o)\n}\nerr := subjRenderer.Render(o, ns, row)","typeGuard":"func isSubjectRes(o any) bool {\n\t_, ok := o.(render.SubjectRes)\n\treturn ok\n}","tryCatchPattern":"if err := subjRenderer.Render(o, ns, row); err != nil {\n\tslog.Warn(\"subject row skipped\", \"type\", fmt.Sprintf(\"%T\", o), slogs.Error, err) // note: error text upstream misreports the type\n\treturn nil // drop the row, keep the view alive\n}","preventionTips":["Subject.Render asserts the value type: pass SubjectRes, not *SubjectRes","Do not trust the type named in this error's message — upstream formats the receiver instead of the payload; log %T of your own payload","Bind the Subject renderer only to subject-producing views","Use comma-ok assertions at custom call sites"],"tags":["kubernetes","go","type-assertion","rbac","error-message","renderer","k9s"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}