derailed/k9s · error

no accessor for %q

Error message

no accessor for %q

What it means

dao.AccessorFor(factory, gvr) failed for the CronJob GVR: the DAO layer could not produce an accessor, so the trigger-Job confirmation dialog aborts. The underlying error is discarded and replaced by this generic message — AccessorFor fails when no DAO is registered for the GVR or the factory/connection is not initialized. Note the real cause is never shown, which hides whether this is a registration gap or a connection problem.

Source

Thrown at internal/view/cronjob.go:101

		ui.KeyT: ui.NewKeyAction("Trigger", c.triggerCmd, true),
		ui.KeyS: ui.NewKeyAction("Suspend/Resume", c.toggleSuspendCmd, true),
	})
}

func (c *CronJob) triggerCmd(evt *tcell.EventKey) *tcell.EventKey {
	fqns := c.GetTable().GetSelectedItems()
	if len(fqns) == 0 {
		return evt
	}
	msg := fmt.Sprintf("Trigger CronJob: %s?", fqns[0])
	if len(fqns) > 1 {
		msg = fmt.Sprintf("Trigger %d CronJobs?", len(fqns))
	}
	d := c.App().Styles.Dialog()
	dialog.ShowConfirm(&d, c.App().Content.Pages, "Confirm Job Trigger", msg, func() {
		res, err := dao.AccessorFor(c.App().factory, c.GVR())
		if err != nil {
			c.App().Flash().Err(fmt.Errorf("no accessor for %q", c.GVR()))
			return
		}
		runner, ok := res.(dao.Runnable)
		if !ok {
			c.App().Flash().Err(fmt.Errorf("expecting a job runner resource for %q", c.GVR()))
			return
		}

		for _, fqn := range fqns {
			if err := runner.Run(fqn); err != nil {
				c.App().Flash().Errf("CronJob trigger failed for %s: %v", fqn, err)
			} else {
				c.App().Flash().Infof("Triggered Job %s %s", c.GVR(), fqn)
			}
		}
	}, func() {})

	return nil

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Confirm standard cronjobs exist on the cluster: kubectl get cronjobs.batch works and appears in discovery.
  2. Reconnect/restart the TUI so the DAO registry and factory initialize against the live cluster.
  3. In custom builds, ensure the DAO for the CronJob GVR is registered before mounting the trigger binding.
  4. Improve diagnostics: wrap and flash the underlying AccessorFor error instead of discarding it (see exampleFix).

Example fix

// before
res, err := dao.AccessorFor(c.App().factory, c.GVR())
if err != nil {
    c.App().Flash().Err(fmt.Errorf("no accessor for %q", c.GVR()))
    return
}

// after: surface the real cause
res, err := dao.AccessorFor(c.App().factory, c.GVR())
if err != nil {
    c.App().Flash().Err(fmt.Errorf("no accessor for %q: %w", c.GVR(), err))
    return
}
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := dao.AccessorFor(c.App().factory, c.GVR()); err != nil {
    c.App().Flash().Err(fmt.Errorf("no accessor for %q: %w", c.GVR(), err))
    return
}

Type guard

func accessorOK(f dao.Factory, gvr *client.GVR) bool {
    _, err := dao.AccessorFor(f, gvr)
    return err == nil
}

Try / catch

res, err := dao.AccessorFor(c.App().factory, c.GVR())
if err != nil {
    // wrap so the real cause (no registration vs no connection) is visible
    c.App().Flash().Err(fmt.Errorf("no accessor for %q: %w", c.GVR(), err))
    return
}
if runner, ok := res.(dao.Runnable); !ok {
    c.App().Flash().Err(fmt.Errorf("resource %q cannot run jobs", c.GVR()))
    return
}

Prevention

When it happens

Trigger: Triggering a CronJob (t key) when the factory has no active connection or the accessor registry lacks an entry for the cronjobs GVR — e.g. a fork/custom build that registers DAOs conditionally, batch API group not in discovery (very old clusters lacking cronjobs), or the confirm dialog racing a disconnect.

Common situations: Custom builds registering CronJob DAO only when the batch CRD is present; disconnected sessions where dialogs were opened before the drop; GVR string mismatches (batch/v1 vs batch/v1beta1 cronjobs) after a cluster upgrade; tests with a stub factory.

Related errors


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