k3s-io/k3s · error
%s error ID %05d
Error message
%s error ID %05d
What it means
SendErrorWithID generates a random 5-digit ID, logs the real error server-side ('<component> error ID 01234: <detail>'), and sends the client only '<component> error ID 01234' with HTTP 500 unless an explicit status was passed. The design avoids information disclosure: the REST response carries no stack or detail, but the ID correlates it to the server log entry containing the root cause.
Source
Thrown at pkg/util/apierrors.go:28
"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]
}
if code == 0 || code == http.StatusOK {
code = http.StatusInternalServerError
}
// Don't log "apiserver not ready" or "apiserver disabled" errors, they are frequent during startup
if !errors.Is(err, ErrAPINotReady) && !errors.Is(err, ErrAPIDisabled) {
logrus.Errorf("Sending %s %d response to %s: %v", req.Proto, code, req.RemoteAddr, err)
}
var serr *apierrors.StatusErrorView on GitHub (pinned to 6ba341e396)
Solutions
- Take the exact ID from the HTTP body and grep the server logs for it (journalctl, kubectl logs, or container logs) to see the underlying error
- If it occurs right after startup, wait for the apiserver/runtime core to become ready and retry
- If persistent, fix the root cause shown in the log line (config, certificates, connectivity) - not the wrapper
- If you operate the client, log the error ID in your own logs/support bundle for correlation with the server
Defensive patterns
Strategy: retry
Type guard
var errIDRe = regexp.MustCompile(`error ID (\d{5})`)
func extractErrorID(body string) (string, bool) {
m := errIDRe.FindStringSubmatch(body)
if m == nil {
return "", false
}
return m[1], true
} Try / catch
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode == http.StatusInternalServerError {
if id, ok := extractErrorID(string(body)); ok {
log.Printf("server error %s: correlate with server log 'error ID %s'", resp.Status, id)
}
// internal errors may be transient (startup, etcd blip): retry with backoff
return retryWithBackoff(req)
} Prevention
- Log the 5-digit error ID client-side immediately; it is the only correlation to server logs
- Retry with backoff on these 500s - many are startup or etcd transients
- Centralize server logs so the 'error ID NNNNN: detail' line can be found later
- Wait for readiness endpoints before first API calls after service startup
When it happens
Trigger: Any handler using SendErrorWithID hitting an internal failure, e.g. the apiserver/runtime core not yet ready, etcd unavailability, or an unexpected error while processing the request.
Common situations: Hitting the REST API while the embedded control plane is still booting; transient etcd/apiserver unavailability; handler bugs surfacing as opaque 500s that confuse users because the body has no detail.
Related errors
- invalid snapshot operation
- invalid username/password combination
- token must not be empty
- etcd datastore disabled
- hijacking not supported
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/e4461682ada334bc.
Report an issue: GitHub.