k3s-io/k3s · warning
etcd disabled
Error message
etcd disabled
What it means
The Bootstrap handler in pkg/server/handlers/handlers.go serves /v1-k3s/bootstrap. When control.Runtime.HTTPBootstrap is nil - true when the datastore is not embedded etcd (SQLite default or external datastore) - the fallback handler logs 'Received HTTP bootstrap request from ..., but embedded etcd is not enabled.' and returns HTTP 400 'etcd disabled'. Only embedded-etcd servers implement HTTP bootstrap.
Source
Thrown at pkg/server/handlers/handlers.go:208
if control.Runtime.Core == nil {
util.SendError(util.ErrCoreNotReady, resp, req, http.StatusServiceUnavailable)
return
}
data := []byte("ok")
resp.WriteHeader(http.StatusOK)
resp.Header().Set("Content-Type", "text/plain")
resp.Header().Set("Content-Length", strconv.Itoa(len(data)))
resp.Write(data)
})
}
func Bootstrap(control *config.Control) http.Handler {
if control.Runtime.HTTPBootstrap != nil {
return control.Runtime.HTTPBootstrap
}
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
logrus.Warnf("Received HTTP bootstrap request from %s, but embedded etcd is not enabled.", req.RemoteAddr)
util.SendError(errors.New("etcd disabled"), resp, req, http.StatusBadRequest)
})
}
func Static(urlPrefix, staticDir string) http.Handler {
return http.StripPrefix(urlPrefix, http.FileServer(http.Dir(staticDir)))
}
// csrSigner wraps a CSR with a Public() method and dummy Sign() method to satisfy the
// crypto.Signer interface required by dynamiclistener's cert helpers.
type csrSigner struct {
csr *x509.CertificateRequest
}
func (c *csrSigner) Public() crypto.PublicKey {
return c.csr.PublicKey
}
func (c csrSigner) Sign(_ io.Reader, _ []byte, _ crypto.SignerOpts) ([]byte, error) {View on GitHub (pinned to 6ba341e396)
Solutions
- Point joining nodes' --server at an embedded-etcd server (in an etcd HA cluster, any etcd member).
- Verify the target server's datastore: 'k3s kubectl get -o json leve... ' or simpler, check that /v1-k3s/bootstrap on an etcd member answers 200.
- If you did not intend a bootstrap call, exclude /v1-k3s/bootstrap from probes/scanners hitting the supervisor port.
Example fix
# before: joining against a SQLite/external-DB server -> 400 etcd disabled k3s server --server https://sqlite-node:6443 --token ... # after: join an embedded-etcd member k3s server --server https://etcd-node:6443 --token ...
Defensive patterns
Strategy: validation
Validate before calling
# Before pointing a join at a server, confirm it runs embedded etcd systemctl show k3s -p ExecStart | grep -q 'etcd' || echo 'target may reject bootstrap'
Try / catch
if resp.StatusCode == http.StatusBadRequest && strings.Contains(body, "etcd disabled") {
// redirect the join to an embedded-etcd server; this node will never serve bootstrap
} Prevention
- Only join nodes to etcd-enabled servers in etcd clusters.
- Keep a documented list of which supervisors run embedded etcd.
- Exclude /v1-k3s/bootstrap from generic probing on non-etcd nodes.
When it happens
Trigger: A node (agent or joining server) sends a bootstrap request to a k3s server whose datastore is SQLite or an external SQL database, i.e. started without embedded etcd. Also seen when a client manually hits /v1-k3s/bootstrap on such a server.
Common situations: Mixed HA setup where a join URL points at a non-etcd server; nodes configured with a --server URL to a SQLite-backed node; curl/health-check traffic probing the endpoint.
Related errors
- no bootstrap data found in datastore - check server token va
- etcd datastore disabled
- no bootstrap data found
- found multiple bootstrap keys in storage
- no bootstrap data is available to reconcile against
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/8177381bafd4de91.
Report an issue: GitHub.