derailed/k9s · error
user is not authorized to scale: %s
Error message
user is not authorized to scale: %s
What it means
scaleRes (internal/dao/dp.go:362-374) scales Deployments and StatefulSets. It authorizes against the scale SUBRESOURCE - client.NewGVR(gvr.String()+":scale") - requiring get AND update on e.g. deployments/scale in the namespace. Denial returns this error printing the GVR (e.g. apps/v1:deployments).
Source
Thrown at internal/dao/dp.go:368
if e.ValueFrom == nil || e.ValueFrom.ConfigMapKeyRef == nil {
continue
}
if e.ValueFrom.ConfigMapKeyRef.Name == name {
return true
}
}
return false
}
func scaleRes(ctx context.Context, f Factory, gvr *client.GVR, path string, replicas int32) error {
ns, n := client.Namespaced(path)
auth, err := f.Client().CanI(ns, client.NewGVR(gvr.String()+":scale"), n, []string{client.GetVerb, client.UpdateVerb})
if err != nil {
return err
}
if !auth {
return fmt.Errorf("user is not authorized to scale: %s", gvr)
}
dial, err := f.Client().Dial()
if err != nil {
return err
}
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{})View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Verify exactly this check: kubectl auth can-i update deployments/scale -n <ns>
- Extend the Role with resources: ["deployments/scale","statefulsets/scale"] (or "*/scale"), verbs: ["get","update"]
- Also keep get/update on the parent resource, which many clients still use
- If scale RBAC is intentionally locked, request scaling through the platform's approved channel
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight the exact subresource check scaleRes performs.
func CanScale(c client.Client, gvr *client.GVR, ns string) (bool, error) {
return c.CanI(ns, client.NewGVR(gvr.String()+":scale"), "", []string{client.GetVerb, client.UpdateVerb})
} Try / catch
if err := scaleRes(ctx, f, gvr, path, n); err != nil {
if strings.Contains(err.Error(), "not authorized to scale") {
return fmt.Errorf("RBAC: grant get+update on %s/scale in %s", gvr, ns)
}
return err
} Prevention
- Remember /scale is a separate RBAC resource: list it explicitly next to its parent
- Test with kubectl auth can-i update deployments/scale -n <ns> when authoring scale roles
- Automate the SSAR pre-check before showing scale UI to users
When it happens
Trigger: Scaling a Deployment/StatefulSet while the identity lacks get/update on the `<resource>/scale` subresource in RBAC (resources: ["deployments/scale"] or ["statefulsets/scale"]). Note: having get/update on deployments itself does not automatically cover the scale subresource in RBAC - subresources are authorized separately.
Common situations: Least-privilege roles that scale via the main resource but forget the /scale subresource entry; clusters where platform teams grant patch-only scaling; impersonated service accounts in automation.
Related errors
- user is not authorized to run jobs
- user is not authorized to (un)suspend cronjobs
- user is not authorized to patch a deployment
- user is not authorized to restart %q
- user is not authorized to delete %s
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/0cf2350396d3df66.
Report an issue: GitHub.