gravitational/teleport · error
respErr.Error()
Error message
respErr.Error()
What it means
In the kube proxy forwarder's error formatting, this writes the status text for the HTTP status code derived from the error (via trace.ErrorToCode) as the response body when a proxied Kubernetes request fails; the literal text is the standard reason phrase (e.g. 'Unauthorized') for the mapped code.
Source
Thrown at lib/kube/proxy/forwarder.go:767
return nil, trace.Wrap(err)
}
err = f.acquireConnectionLockWithIdentity(req.Context(), authContext)
if err != nil {
return nil, trace.Wrap(err)
}
return handler(authContext, w, req, p)
}, f.formatStatusResponseError)
}
func (f *Forwarder) formatForwardResponseError(rw http.ResponseWriter, r *http.Request, respErr error) {
f.formatStatusResponseError(rw, respErr)
}
// writeResponseErrorToBody writes the error response to the body without any formatting.
// It is used for the /version endpoint since Kubernetes doesn't expect a JSON response
// for that endpoint.
func (f *Forwarder) writeResponseErrorToBody(rw http.ResponseWriter, respErr error) {
http.Error(rw, respErr.Error(), http.StatusInternalServerError)
}
// formatForwardResponseError handles errors returned from requests to the Kubernetes API.
// Any errors produced as a result of a GOAWAY request are forwarded to users as [http.StatusTooManyRequests]
// with a Retry-After header set to inform clients that they should retry the request. All
// other errors are formatted as a [metav1.Status] and written to the [http.ResponseWriter].
func (f *Forwarder) formatStatusResponseError(rw http.ResponseWriter, respErr error) {
// This detects failed requests that were terminated by the server due to GOAWAY. There
// is no direct way to detect these errors. No exported constants or error types exist from the
// standard library, so we have to match on the error message. The two error strings come from:
// - golang.org/x/net/http2 when its internal retry path cannot replay the body:
// https://github.com/golang/net/blob/5ac9daca088ab4f378d7df849f6c7d28bea86071/http2/transport.go#L694
// - net/http (errCannotRewind) when, after the http2 conn pool is drained, the http1 retry
// path tries to rewind the body and fails because Request.GetBody is unset:
// https://github.com/golang/go/blob/go1.26.2/src/net/http/transport.go#L759
// When a failed request is found, we return a response that indicates to clients that they
// should retry the request themselves.
errString := respErr.Error()View on GitHub (pinned to 1283425b60)
Solutions
- Check the Kubernetes client's output and proxy logs for the underlying error
- Address the root cause per the status code: authenticate (401), fix RBAC permissions (403), or verify the resource exists (404)
- Retry transient failures (5xx)
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at lib/kube/proxy/forwarder.go:767 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/b24df33f99073548.
Report an issue: GitHub.