k3s-io/k3s · warning

apiserver not ready

Error message

apiserver not ready

What it means

ErrAPINotReady (pkg/util/apierrors.go) is sent as HTTP 503 by handlers.APIServer when a request to the proxied kube-apiserver routes (/k8s/... on the supervisor port) arrives but control.Runtime.APIServer is nil - the apiserver handler has not been installed yet. It marks the startup window or a failed apiserver launch, and util.IsAPIServerError treats it (and ErrAPIDisabled) specially for retry logic.

Source

Thrown at pkg/util/apierrors.go:18

package util

import (
	"crypto/rand"
	"errors"
	"fmt"
	"math/big"
	"net/http"

	"github.com/k3s-io/api/pkg/generated/clientset/versioned/scheme"
	"github.com/sirupsen/logrus"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
)

var ErrAPINotReady = errors.New("apiserver not ready")
var ErrAPIDisabled = errors.New("apiserver disabled")
var ErrCoreNotReady = errors.New("runtime core not ready")

// SendErrorWithID sends and logs a random error ID so that logs can be correlated
// between the REST API (which does not provide any detailed error output, to avoid
// information disclosure) and the server logs.
func SendErrorWithID(err error, component string, resp http.ResponseWriter, req *http.Request, status ...int) {
	errID, _ := rand.Int(rand.Reader, big.NewInt(99999))
	logrus.Errorf("%s error ID %05d: %v", component, errID, err)
	SendError(fmt.Errorf("%s error ID %05d", component, errID), resp, req, status...)
}

// SendError sends a properly formatted error response
func SendError(err error, resp http.ResponseWriter, req *http.Request, status ...int) {
	var code int
	if len(status) == 1 {
		code = status[0]
	}

View on GitHub (pinned to 6ba341e396)

Solutions

  1. Retry with backoff until /readyz (or the supervisor's readyz route) succeeds - this error is expected to be transient.
  2. If it persists, check k3s logs for kube-apiserver startup failures (bad --kube-apiserver-arg, cert problems, etcd unavailable).
  3. Point clients at a load balancer that health-checks /readyz so unready servers are skipped.
  4. Verify disk/CPU headroom on the server; slow etcd delays apiserver readiness.

Example fix

# before: one-shot call may hit 503 apiserver not ready
curl -sk https://127.0.0.1:6443/k8s/version

# after: gate on readiness
until curl -sk https://127.0.0.1:6443/readyz >/dev/null; do sleep 2; done
curl -sk https://127.0.0.1:6443/k8s/version
Defensive patterns

Strategy: retry

Validate before calling

# Gate any /k8s call on readiness first
until curl -sk https://127.0.0.1:6443/readyz >/dev/null 2>&1; do sleep 2; done

Try / catch

if errors.Is(err, util.ErrAPINotReady) || resp.StatusCode == http.StatusServiceUnavailable {
    // startup window: retry with backoff; escalate only after readyz stays green and calls still fail
}

Prevention

When it happens

Trigger: Hitting the supervisor's apiserver proxy route before kube-apiserver finished initializing, or after apiserver startup failed so Runtime.APIServer was never set. Agents and clients using the supervisor port as their kube-apiserver endpoint see this during early startup.

Common situations: Scripts that target 6443 immediately after k3s starts; first-boot joins; control planes slow under load (etcd compaction, disk pressure) so apiserver init takes minutes.

Related errors


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/40b2b34fbf1c3b3b. Report an issue: GitHub.