derailed/k9s · error

expecting a scalable resource for %q

Error message

expecting a scalable resource for %q

What it means

ScaleExtender.scale (internal/view/scale_extender.go:225) resolves the DAO for the GVR and asserts dao.Scalable (Scale(ctx, path, replicas)). If the accessor does not implement Scale, scaling is refused. In practice only DAOs for resources exposing the Kubernetes scale subresource implement it.

Source

Thrown at internal/view/scale_extender.go:225

			SetBackgroundColorActivated(styles.ButtonFocusBgColor.Color()).
			SetLabelColorActivated(styles.ButtonFocusFgColor.Color())
	}

	return f, nil
}

func (s *ScaleExtender) dismissDialog() {
	s.App().Content.RemovePage(scaleDialogKey)
}

func (s *ScaleExtender) scale(ctx context.Context, path string, replicas int32) error {
	res, err := dao.AccessorFor(s.App().factory, s.GVR())
	if err != nil {
		return err
	}
	scaler, ok := res.(dao.Scalable)
	if !ok {
		return fmt.Errorf("expecting a scalable resource for %q", s.GVR())
	}

	return scaler.Scale(ctx, path, replicas)
}

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Verify the resource actually supports scaling (deployments, replicasets, statefulsets do)
  2. For a CRD, add the scale subresource to the CRD spec (subresources.scale with statusReplicasPath / specReplicasPath / labelSelectorPath) so its DAO can implement Scale
  3. Scale via kubectl to confirm server-side support: 'kubectl scale --replicas=N <gvr>/<name>'; if the server rejects it, the resource is not scalable at all
  4. Remove the scale keybinding from non-scalable views

Example fix

# before: CRD without scale subresource -> expecting a scalable resource for "mycrds.example.com"
# after: add to CRD spec
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
spec:
  versions:
    - name: v1
      subresources:
        scale:
          specReplicasPath: .spec.replicas
          statusReplicasPath: .status.replicas
          labelSelectorPath: .status.labelSelector
Defensive patterns

Strategy: type-guard

Validate before calling

// capability check before scaling
res, err := dao.AccessorFor(s.App().factory, s.GVR())
if err != nil { return err }
if _, ok := res.(dao.Scalable); !ok {
    return fmt.Errorf("%s does not support scale; add a scale subresource or use kubectl", s.GVR())
}

Type guard

func isScalable(res dao.Resource) (dao.Scalable, bool) {
    sc, ok := res.(dao.Scalable)
    return sc, ok
}

Prevention

When it happens

Trigger: Pressing the scale keybinding on a GVR whose DAO lacks Scale — custom CRDs without a scale subresource, or a generic accessor registered for an alias.

Common situations: Trying to scale CRDs (operators) that do not define `subresources: [scale]` in their CRD spec; k9s forks attaching ScaleExtender broadly; interface drift after upgrades.

Related errors


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