error: You must be logged in to the server (Unauthorized) — how to fix
error: You must be logged in to the server (Unauthorized)
Quick fix: Check which context you're using (kubectl config current-context). Then refresh credentials: EKS aws eks update-kubeconfig --name CLUSTER --region REGION (and aws sts get-caller-identity), GKE gcloud container clusters get-credentials CLUSTER, AKS az aks get-credentials -g RG -n CLUSTER (and kubelogin convert-kubeconfig -l azurecli). kubeadm: renew certs with kubeadm certs renew all and copy the new admin.conf.
What it means
Unauthorized (401) means authentication failed: the API server doesn't accept who you claim to be. That's different from Forbidden (403), where it knows who you are but RBAC denies the action.
Start by checking where kubectl is pointing and what credentials it uses:
kubectl config current-context
kubectl config view --minify # server, user, auth method
kubectl get --raw /version -v=6 # shows the request and the 401
Cause 1: wrong context
You may be using credentials for cluster A against cluster B, e.g. after merging kubeconfigs.
kubectl config get-contexts
kubectl config use-context my-cluster
Cause 2: EKS — AWS identity not mapped or expired
EKS authenticates via your AWS identity (aws eks get-token). Check which identity you are and refresh the kubeconfig:
aws sts get-caller-identity
aws eks update-kubeconfig --name my-cluster --region eu-west-1
If you switched AWS profiles or SSO sessions expired, log in again (aws sso login --profile X) and make sure the kubeconfig uses that profile (--profile X on update-kubeconfig).
If the identity is valid but not granted access to the cluster, you also get Unauthorized. A cluster admin must add it — either an access entry:
aws eks create-access-entry --cluster-name my-cluster \
--principal-arn arn:aws:iam::123456789012:role/dev
aws eks associate-access-policy --cluster-name my-cluster \
--principal-arn arn:aws:iam::123456789012:role/dev \
--policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy \
--access-scope type=cluster
or, on clusters using the older method, a mapping in the aws-auth ConfigMap in kube-system. Note: the IAM identity that created the cluster has admin access implicitly; others don't.
Cause 3: GKE / AKS token expired
# GKE (needs the gke-gcloud-auth-plugin)
gcloud auth login
gcloud container clusters get-credentials my-cluster --region europe-west1
# AKS with Entra ID
az login
az aks get-credentials -g my-rg -n my-cluster --overwrite-existing
kubelogin convert-kubeconfig -l azurecli
Cause 4: kubeadm client certificate expired
Certificates generated by kubeadm are valid for one year. After that, admin.conf stops working. On a control-plane node:
sudo kubeadm certs check-expiration
sudo kubeadm certs renew all
sudo systemctl restart kubelet # then restart control-plane static pods
mkdir -p ~/.kube
sudo cp /etc/kubernetes/admin.conf ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
Restart the static pods (kube-apiserver, controller-manager, scheduler, etcd) so they load the new certs, e.g. by temporarily moving their manifests out of /etc/kubernetes/manifests and back.
Cause 5: deleted or rotated ServiceAccount token
A kubeconfig built from a ServiceAccount token breaks if the token Secret was deleted or the token (from kubectl create token) expired — those default to one hour. Create a new one with a longer duration if appropriate:
kubectl create token ci-bot -n ci --duration=24h
Cause 6: k3s / minikube / kind cluster recreated
Recreating a local cluster generates a new CA and credentials. Re-export the kubeconfig: minikube update-context, kind export kubeconfig --name NAME, or copy /etc/rancher/k3s/k3s.yaml again.
Last updated 2026-11-04.