derailed/k9s · error
no context for gvr found
Error message
no context for gvr found
What it means
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.
Source
Thrown at internal/dao/reference.go:27
"github.com/derailed/k9s/internal"
"github.com/derailed/k9s/internal/client"
"github.com/derailed/k9s/internal/render"
"k8s.io/apimachinery/pkg/runtime"
)
var _ Accessor = (*Reference)(nil)
// Reference represents cluster resource references.
type Reference struct {
NonResource
}
// List collects all references.
func (r *Reference) List(ctx context.Context, _ string) ([]runtime.Object, error) {
gvr, ok := ctx.Value(internal.KeyGVR).(*client.GVR)
if !ok {
return nil, errors.New("no context for gvr found")
}
switch gvr {
case client.SaGVR:
return r.ScanSA(ctx)
default:
return r.Scan(ctx)
}
}
// Get fetch a given reference.
func (*Reference) Get(context.Context, string) (runtime.Object, error) {
panic("NYI")
}
// Scan scan cluster resources for references.
func (r *Reference) Scan(ctx context.Context) ([]runtime.Object, error) {
refs, err := ScanForRefs(ctx, r.Factory)
if err != nil {View on GitHub (pinned to 2d3ccc6ba2)
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.
Example fix
// before ctx := context.Background() oo, err := ref.List(ctx, "") // after ctx = context.WithValue(ctx, internal.KeyGVR, client.SaGVR) oo, err := ref.List(ctx, "")
Defensive patterns
Strategy: validation
Validate before calling
func hasGVR(ctx context.Context) bool {
_, ok := ctx.Value(internal.KeyGVR).(*client.GVR)
return ok
}
// before calling List:
if !hasGVR(ctx) {
ctx = context.WithValue(ctx, internal.KeyGVR, client.SaGVR)
} Type guard
func gvrFromCtx(ctx context.Context) (*client.GVR, bool) {
g, ok := ctx.Value(internal.KeyGVR).(*client.GVR)
return g, ok
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- expecting context Path
- expecting a SubjectKind
- no screendump dir found in context
- no benchmark dir found in context
- no path specified in context
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/06a204bcaf61d046.
Report an issue: GitHub.