derailed/k9s · error

no component found for %s

Error message

no component found for %s

What it means

The command executed and resolved to a GVR, but the component factory returned nil — no viewer is registered that can display this GVR. The registry (customViewers plus generic browser fallback) had no entry for the resource, so there is no component to inject into the UI stack.

Source

Thrown at internal/view/command.go:370

func (c *Command) exec(p *cmd.Interpreter, gvr *client.GVR, comp model.Component, clearStack, pushCmd bool) (err error) {
	defer func() {
		if e := recover(); e != nil {
			slog.Error("Failure detected during command exec", slogs.Error, e)
			c.app.Content.Dump()
			slog.Debug("Dumping history buffer", slogs.CmdHist, c.app.cmdHistory.List())
			slog.Error("Dumping stack", slogs.Stack, string(debug.Stack()))

			ci := cmd.NewInterpreter(podCmd)
			currentCommand, ok := c.app.cmdHistory.Top()
			if ok {
				ci = ci.Reset(currentCommand, "")
			}
			err = c.run(ci, "", true, true)
		}
	}()

	if comp == nil {
		return fmt.Errorf("no component found for %s", gvr)
	}
	comp.SetCommand(p)

	if clearStack {
		v := contextRX.ReplaceAllString(p.GetLine(), "")
		c.app.Config.SetActiveView(v)
	}
	if err := c.app.inject(comp, clearStack); err != nil {
		return err
	}
	if pushCmd {
		c.app.cmdHistory.Push(p.GetLine())
	}
	slog.Debug("History (exec)", slogs.Stack, strings.Join(c.app.cmdHistory.List(), "|"))

	return
}

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Use the normal command path (alias -> browser) which always has the generic browser fallback, instead of calling the component-inject path with raw GVRs.
  2. Register a custom viewer for the GVR in customViewers (or the user custom-view config) before navigating to it.
  3. Verify the GVR string (group/version/resource) is exactly what discovery reports.
  4. If it happens for standard resources on startup, reconnect/restart so the viewer registry completes initialization.

Example fix

// before: rely on registry for unknown gvr
comp := componentFor(gvr) // may be nil

// after: register a fallback viewer first
customViewers[*gvr] = MetaViewer{viewerFn: func(g *client.GVR) ResourceViewer { return NewBrowser(g) }}
Defensive patterns

Strategy: validation

Validate before calling

if comp := componentFor(gvr); comp == nil {
    return fmt.Errorf("no viewer for %s — register one or use the generic browser", gvr)
}
comp.SetCommand(p)

Type guard

func hasViewer(gvr *client.GVR) bool {
    _, ok := customViewers[*gvr]
    return ok || hasGenericFallback(gvr)
}

Try / catch

if err := c.exec(p, gvr, comp, clearStack, pushCmd); err != nil {
    if strings.Contains(err.Error(), "no component found") {
    slog.Error("missing viewer registration", "gvr", gvr)
    }
}

Prevention

When it happens

Trigger: A GVR string that resolves via alias but has no viewer mapping — malformed/custom group-version-resource that bypassed customViewers registration; a programmatic call to the exec/inject path with a GVR never registered; race where the viewers map is not yet initialized at startup.

Common situations: Custom resources expected to render generically but hitting a restricted path; forks adding GVRs without registering viewers; version changes to the viewer registry; invoking internal APIs directly rather than through the command layer.

Related errors


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