{"record":{"id":"06a204bcaf61d046","repo":"derailed/k9s","slug":"no-context-for-gvr-found","errorCode":null,"errorMessage":"no context for gvr found","messagePattern":"no context for gvr found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/reference.go","lineNumber":27,"sourceCode":"\n\t\"github.com/derailed/k9s/internal\"\n\t\"github.com/derailed/k9s/internal/client\"\n\t\"github.com/derailed/k9s/internal/render\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\nvar _ Accessor = (*Reference)(nil)\n\n// Reference represents cluster resource references.\ntype Reference struct {\n\tNonResource\n}\n\n// List collects all references.\nfunc (r *Reference) List(ctx context.Context, _ string) ([]runtime.Object, error) {\n\tgvr, ok := ctx.Value(internal.KeyGVR).(*client.GVR)\n\tif !ok {\n\t\treturn nil, errors.New(\"no context for gvr found\")\n\t}\n\tswitch gvr {\n\tcase client.SaGVR:\n\t\treturn r.ScanSA(ctx)\n\tdefault:\n\t\treturn r.Scan(ctx)\n\t}\n}\n\n// Get fetch a given reference.\nfunc (*Reference) Get(context.Context, string) (runtime.Object, error) {\n\tpanic(\"NYI\")\n}\n\n// Scan scan cluster resources for references.\nfunc (r *Reference) Scan(ctx context.Context) ([]runtime.Object, error) {\n\trefs, err := ScanForRefs(ctx, r.Factory)\n\tif err != nil {","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/reference.go#L9-L45","documentation":"Reference.List reads the target GVR from the request context (ctx.Value(internal.KeyGVR)) before deciding whether to scan for serviceaccount references or generic references. If the context does not carry a *client.GVR under internal.KeyGVR (wrong type or key absent), List refuses to proceed. This is a programmer contract: the view layer (e.g. internal/view/browser.go:637) must inject the GVR before invoking the DAO.","triggerScenarios":"Calling dao.Reference.List(ctx, ...) with a plain context.Background() or any ctx that was never decorated with context.WithValue(ctx, internal.KeyGVR, gvr); storing a non-*client.GVR value under the key also fails the type assertion.","commonSituations":"Custom views or integration tests that drive the Reference DAO directly instead of going through Browser/tableView plumbing; refactoring a view that sets KeyGVR on one code path but not another (e.g. a new enter/navigation branch); typo'd ContextKey.","solutions":["Wrap the context before listing: ctx = context.WithValue(ctx, internal.KeyGVR, client.SaGVR) (or the relevant GVR) exactly as internal/view/browser.go:637 does.","If writing a custom view, model it on existing callers (view/rbac.go:47-48, view/vul_extender.go:48-49) that set both KeyGVR and KeyPath.","Verify the value stored is of concrete type *client.GVR, not client.GVR or string, so the type assertion succeeds."],"exampleFix":"// before\nctx := context.Background()\noo, err := ref.List(ctx, \"\")\n// after\nctx = context.WithValue(ctx, internal.KeyGVR, client.SaGVR)\noo, err := ref.List(ctx, \"\")","handlingStrategy":"validation","validationCode":"func hasGVR(ctx context.Context) bool {\n    _, ok := ctx.Value(internal.KeyGVR).(*client.GVR)\n    return ok\n}\n\n// before calling List:\nif !hasGVR(ctx) {\n    ctx = context.WithValue(ctx, internal.KeyGVR, client.SaGVR)\n}","typeGuard":"func gvrFromCtx(ctx context.Context) (*client.GVR, bool) {\n    g, ok := ctx.Value(internal.KeyGVR).(*client.GVR)\n    return g, ok\n}","tryCatchPattern":null,"preventionTips":["Centralize context construction in one helper that always sets KeyGVR and KeyPath together.","In tests, seed the context with the same keys production views use.","Store only *client.GVR values under internal.KeyGVR."],"tags":["go","kubernetes","context","dao","programmer-error"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}