derailed/k9s · error

unsupported resource for scaling: %s

Error message

unsupported resource for scaling: %s

What it means

scaleRes (internal/dao/dp.go:394-396) supports exactly two GVRs - client.DpGVR (Deployments) and client.StsGVR (StatefulSets). Any other GVR that reaches this generic helper falls through the switch's default and is rejected with this message printing the GVR.

Source

Thrown at internal/dao/dp.go:394

	switch gvr {
	case client.DpGVR:
		scale, e := dial.AppsV1().Deployments(ns).GetScale(ctx, n, metav1.GetOptions{})
		if e != nil {
			return e
		}
		scale.Spec.Replicas = replicas
		_, e = dial.AppsV1().Deployments(ns).UpdateScale(ctx, n, scale, metav1.UpdateOptions{})
		return e
	case client.StsGVR:
		scale, e := dial.AppsV1().StatefulSets(ns).GetScale(ctx, n, metav1.GetOptions{})
		if e != nil {
			return e
		}
		scale.Spec.Replicas = replicas
		_, e = dial.AppsV1().StatefulSets(ns).UpdateScale(ctx, n, scale, metav1.UpdateOptions{})
		return e
	default:
		return fmt.Errorf("unsupported resource for scaling: %s", gvr)
	}
}

func restartRes[T runtime.Object](ctx context.Context, f Factory, gvr *client.GVR, path string, opts *metav1.PatchOptions) error {
	o, err := f.Get(gvr, path, true, labels.Everything())
	if err != nil {
		return err
	}
	var r = new(T)
	err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, r)
	if err != nil {
		return err
	}

	ns, n := client.Namespaced(path)
	auth, err := f.Client().CanI(ns, gvr, n, client.PatchAccess)
	if err != nil {
		return err

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Scale only Deployments or StatefulSets through this path
  2. For other scalable kinds, use the resource-specific client (e.g. dial.AppsV1().ReplicaSets(ns).UpdateScale) or kubectl scale
  3. If you control the code, add a case for the GVR before the default branch

Example fix

// before
scaleRes(ctx, f, client.RsGVR, path, 3) // falls into default
// after
case client.RsGVR:
    scale, e := dial.AppsV1().ReplicaSets(ns).GetScale(ctx, n, metav1.GetOptions{})
    if e != nil { return e }
    scale.Spec.Replicas = replicas
    _, e = dial.AppsV1().ReplicaSets(ns).UpdateScale(ctx, n, scale, metav1.UpdateOptions{})
    return e
Defensive patterns

Strategy: type-guard

Validate before calling

// Reject unsupported GVRs before any authorization or API traffic.
func Scalable(gvr *client.GVR) bool {
	return gvr == client.DpGVR || gvr == client.StsGVR
}

Type guard

func ScaleTarget(gvr *client.GVR) (apply func(ctx context.Context, ns, name string, replicas int32) error, err error) {
    switch gvr {
    case client.DpGVR:
        return applyDpScale, nil
    case client.StsGVR:
        return applyStsScale, nil
    default:
        return nil, fmt.Errorf("unsupported resource for scaling: %s", gvr)
    }
}

Try / catch

if !Scalable(gvr) { return fmt.Errorf("unsupported resource for scaling: %s", gvr) }
return scaleRes(ctx, f, gvr, path, replicas)

Prevention

When it happens

Trigger: Routing a scale request for an unsupported kind through scaleRes - e.g. a Replicaset, ReplicationController, or a custom CRD with a scale subresource. Authorization (error 113) is checked before this switch, so you only see this error after RBAC passed.

Common situations: Extending k9s DAOs or writing plugins that call the scale path for other controllers; version drift where a caller assumed a GVR was added to the supported set.

Related errors


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