{"record":{"id":"21d4604acad20e0f","repo":"derailed/k9s","slug":"expecting-a-subjectkind","errorCode":null,"errorMessage":"expecting a SubjectKind","messagePattern":"expecting a SubjectKind","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/rbac_subject.go","lineNumber":29,"sourceCode":"\t\"github.com/derailed/k9s/internal/render\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\nvar (\n\t_ Accessor = (*Subject)(nil)\n\t_ Nuker    = (*Subject)(nil)\n)\n\n// Subject represents a subject model.\ntype Subject struct {\n\tResource\n}\n\n// List returns a collection of subjects.\nfunc (s *Subject) List(ctx context.Context, _ string) ([]runtime.Object, error) {\n\tkind, ok := ctx.Value(internal.KeySubjectKind).(string)\n\tif !ok {\n\t\treturn nil, errors.New(\"expecting a SubjectKind\")\n\t}\n\n\tcrbs, err := s.listClusterRoleBindings(kind)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trbs, err := s.listRoleBindings(kind)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor _, rb := range rbs {\n\t\tcrbs = crbs.Upsert(rb)\n\t}\n\n\too := make([]runtime.Object, len(crbs))\n\tfor i, o := range crbs {","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/rbac_subject.go#L11-L47","documentation":"The Subject DAO backs the RBAC subject browser for users, groups and serviceaccounts. Because a subject's kind cannot be derived from cluster data, List requires it pre-seeded in the context under internal.KeySubjectKind as a string (internal/dao/rbac_subject.go:29); the stock views inject it via their context functions (view/user.go, view/group.go, view/sa.go). An absent key returns 'expecting a SubjectKind' before any cluster call is made.","triggerScenarios":"Calling dao.Subject.List with a context that never had context.WithValue(ctx, internal.KeySubjectKind, kind) — direct DAO use in tests, plugins or embedded tools, or a custom view that forgot to mirror the contextFn pattern of the user/group/sa views. Storing a non-string value under the key fails the same assertion.","commonSituations":"Programmatic use of the DAO layer outside the TUI; refactored or custom RBAC views building their own context; unit tests calling Subject.List on context.Background().","solutions":["Seed the kind before listing: ctx = context.WithValue(ctx, internal.KeySubjectKind, \"User\") with one of User|Group|ServiceAccount.","When writing views, copy the contextFn pattern from internal/view/user.go, view/group.go and view/sa.go.","Ensure the stored value is a plain string; other types fail the assertion.","In tests, seed KeySubjectKind the way internal/dao tests seed other context keys."],"exampleFix":"// before\nctx := context.Background()\nsubs, err := subjectDAO.List(ctx, \"\") // -> expecting a SubjectKind\n// after\nctx := context.WithValue(context.Background(), internal.KeySubjectKind, \"Group\")\nsubs, err := subjectDAO.List(ctx, \"\")","handlingStrategy":"validation","validationCode":"kind := \"User\" // one of User|Group|ServiceAccount\nif _, ok := ctx.Value(internal.KeySubjectKind).(string); !ok {\n    ctx = context.WithValue(ctx, internal.KeySubjectKind, kind)\n}\nsubs, err := subjectDAO.List(ctx, \"\")","typeGuard":"func subjectKindFrom(ctx context.Context) (string, bool) {\n    k, ok := ctx.Value(internal.KeySubjectKind).(string)\n    return k, ok && (k == \"User\" || k == \"Group\" || k == \"ServiceAccount\")\n}","tryCatchPattern":null,"preventionTips":["Always seed internal.KeySubjectKind before calling Subject.List; kind is not derivable from the cluster.","Reuse the contextFn pattern from view/user.go, view/group.go and view/sa.go in custom views.","Keep the value a plain string with one of the three exact kinds.","In unit tests, seed context keys exactly as the dao tests do."],"tags":["kubernetes","go","context","rbac","dao"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}