derailed/k9s · error

expecting context Wait

Error message

expecting context Wait

What it means

Returned by ScanForSARefs (internal/dao/cluster.go:116) when ctx.Value(internal.KeyWait) is not a bool. KeyWait controls whether reference scans use the informer cache with wait (blocking sync) or hit the API directly. Notably ScanForRefs only logs a warning for the same omission, but ScanForSARefs treats it as a hard error.

Source

Thrown at internal/dao/cluster.go:116

	}()

	res := make(Refs, 0, 10)
	for refs := range out {
		res = append(res, refs...)
	}

	return res, nil
}

// ScanForSARefs scans cluster resources for serviceaccount refs.
func ScanForSARefs(ctx context.Context, f Factory) (Refs, error) {
	fqn, ok := ctx.Value(internal.KeyPath).(string)
	if !ok {
		return nil, errors.New("expecting context Path")
	}
	wait, ok := ctx.Value(internal.KeyWait).(bool)
	if !ok {
		return nil, errors.New("expecting context Wait")
	}

	var wg sync.WaitGroup
	out := make(chan Refs)
	for gvr, scanner := range scanners() {
		wg.Add(1)
		go func(ctx context.Context, gvr *client.GVR, s RefScanner, out chan Refs, wait bool) {
			defer wg.Done()
			s.Init(f, gvr)
			refs, err := s.ScanSA(ctx, fqn, wait)
			if err != nil {
				slog.Error("ServiceAccount scan failed",
					slogs.RefType, fmt.Sprintf("%T", s),
					slogs.Error, err,
				)
				return
			}
			select {

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Always set KeyWait explicitly: context.WithValue(ctx, internal.KeyWait, false) for instant (cache-less) scans or true to wait for cache sync
  2. Use one shared context-enrichment helper for both scans and include all keys even when optional elsewhere
  3. Keep the value a raw bool, not a pointer or custom type

Example fix

// before
ctx := context.WithValue(ctx, internal.KeyPath, fqn)
refs, err := dao.ScanForSARefs(ctx, factory)

// after
ctx = context.WithValue(ctx, internal.KeyWait, true)
refs, err := dao.ScanForSARefs(ctx, factory)
Defensive patterns

Strategy: validation

Validate before calling

ctx = context.WithValue(ctx, internal.KeyWait, false) // or true to wait for cache sync
refs, err := dao.ScanForSARefs(ctx, factory)

Try / catch

refs, err := dao.ScanForSARefs(ctx, factory)
if err != nil && strings.Contains(err.Error(), "expecting context Wait") {
    ctx = context.WithValue(ctx, internal.KeyWait, true)
    refs, err = dao.ScanForSARefs(ctx, factory)
}

Prevention

When it happens

Trigger: Calling ScanForSARefs with KeyPath set but omitting context.WithValue(ctx, internal.KeyWait, b); storing a *bool or any non-bool under the key makes the assertion fail identically.

Common situations: Callers copying the ScanForRefs contract (where Wait is optional) into ScanForSARefs; refactors that default wait at the call site instead of the context; tests building minimal contexts.

Related errors


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