ahmetb/kubectx · error
failed to create transport: %w
Error message
failed to create transport: %w
What it means
This error is returned by proxy.Start when rest.TransportFor(restCfg) fails to build an http.RoundTripper from the loaded kubeconfig REST config. TransportFor validates and materializes the TLS, client-cert, bearer-token, exec-credential, and proxy settings from the rest.Config, so any invalid or unusable credential material in the kubeconfig surfaces here. It is a wrapping error: the underlying client-go cause (e.g. x509 parse failure) is embedded via %w.
Source
Thrown at internal/proxy/readonly.go:78
// GET, HEAD, and OPTIONS requests (without protocol upgrades) to the real API server.
func Start(cfg Config) (*ReadonlyProxy, error) {
loadingRules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: cfg.KubeconfigPath}
overrides := &clientcmd.ConfigOverrides{CurrentContext: cfg.ContextName}
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides)
restCfg, err := clientConfig.ClientConfig()
if err != nil {
return nil, fmt.Errorf("failed to load kubeconfig: %w", err)
}
targetURL, err := url.Parse(restCfg.Host)
if err != nil {
return nil, fmt.Errorf("failed to parse server URL %q: %w", restCfg.Host, err)
}
transport, err := rest.TransportFor(restCfg)
if err != nil {
return nil, fmt.Errorf("failed to create transport: %w", err)
}
handler := NewHandler(targetURL, transport)
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, fmt.Errorf("failed to listen: %w", err)
}
srv := &http.Server{Handler: handler}
go srv.Serve(listener)
debugLog.Printf("started on %s, proxying to %s", listener.Addr(), targetURL)
return &ReadonlyProxy{
server: srv,
listener: listener,
}, nilView on GitHub (pinned to 12ad6fb22e)
Solutions
- Run the exec/auth plugin manually (e.g. `aws eks get-token --cluster-name ...` or `gke-gcloud-auth-plugin`) to see the underlying cause and install/repair it if missing
- Inspect the current context's user/cluster in the kubeconfig (`kubectl config view --raw`) and fix or regenerate the certificate/key/CA data (`aws eks update-kubeconfig`, `gcloud container clusters get-credentials`, etc.)
- Check that certificate file paths in the kubeconfig exist and that cert and key match (compare modulus/fingerprints)
- Switch KUBECONFIG or --context to a known-good context to isolate whether the problem is credential material
- Set KUBECTX_DEBUG=1 and re-run; the wrapped client-go error text names the exact field that failed
Example fix
// before (exec plugin missing)
users:
- name: my-user
user:
exec:
command: gke-gcloud-auth-plugin # not installed
// after
// install the plugin first:
// gcloud components install gke-gcloud-auth-plugin
users:
- name: my-user
user:
exec:
command: /usr/local/bin/gke-gcloud-auth-plugin
apiVersion: client.authentication.k8s.io/v1beta1 Defensive patterns
Strategy: try-catch
Validate before calling
// Go: validate kubeconfig credential material before calling proxy.Start
func validateKubeconfig(path, ctxName string) error {
loadingRules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: path}
overrides := &clientcmd.ConfigOverrides{CurrentContext: ctxName}
cc := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, overrides)
restCfg, err := cc.ClientConfig()
if err != nil {
return fmt.Errorf("kubeconfig load: %w", err)
}
if restCfg.Host == "" {
return fmt.Errorf("context %q has no server", ctxName)
}
if restCfg.ExecProvider != nil {
if _, err := exec.LookPath(restCfg.ExecProvider.Command); err != nil {
return fmt.Errorf("exec plugin %q not installed", restCfg.ExecProvider.Command)
}
}
return nil
} Type guard
func isTransportConfigError(err error) bool {
// narrow the wrapped cause before deciding how to react
var ce *x509.CertificateInvalidError
if errors.As(err, &ce) {
return true // expired/untrusted cert: fix kubeconfig, no retry
}
return strings.Contains(err.Error(), "failed to create transport")
} Try / catch
p, err := proxy.Start(cfg)
if err != nil {
if strings.Contains(err.Error(), "failed to create transport") {
var pe *exec.Error
if errors.As(err, &pe) {
return fmt.Errorf("auth plugin %s not found: %w", pe.Name, err)
}
return fmt.Errorf("bad credential material in kubeconfig: %w", err)
}
return err
} Prevention
- Regenerate kubeconfig credentials with the cloud CLI (aws eks update-kubeconfig, gcloud container clusters get-credentials) instead of hand-editing base64 cert blocks
- Keep auth exec plugins (aws, gcloud, azure) installed and on PATH; verify with a plain `kubectl get nodes` before invoking the library
- Run `kubectl config view --raw --minify` to confirm the active context has a valid server, CA, and client credential
- Check cert/key/CA file paths are absolute and readable by the process
- Use `errors.As` on the wrapped error to distinguish exec-plugin failures from TLS failures
When it happens
Trigger: rest.TransportFor fails when the kubeconfig context referenced by Config.ContextName points to a cluster/user with malformed TLS data (bad certificate or key PEM), a client cert/key pair that does not match, an exec credential plugin that is missing, not executable, or exits non-zero, or an invalid CA file path / proxy URL.
Common situations: Kubeconfig generated by an older cluster bootstrap with expired or corrupt client certificates; KUBECONFIG pointing at a context whose user uses an exec plugin (aws eks get-token, gke-gcloud-auth-plugin) that is not installed or not on PATH; a certificate-authority path moved or deleted; hand-edited kubeconfig with base64 padding mistakes.
Related errors
- kubeconfig error: %w
- failed to get current context: %w
- failed to read namespace of "%s": %w
- kubeconfig error: %w
- failed to switch namespace: %w
AI-assisted analysis of ahmetb/kubectx@12ad6fb22e (2026-09-02).
Data as JSON: /api/errors/37f1167af177f1fd.
Report an issue: GitHub.