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

  1. 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.
  2. 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.
  3. 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

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


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/06a204bcaf61d046. Report an issue: GitHub.