probelabs/goreplay · critical

err.Error()

Error message

err.Error()

What it means

k8sIPs resolves a Kubernetes address scheme to pod IPs. It first calls rest.InClusterConfig(); when the process is not running inside a Kubernetes cluster (no service account token/CA mounted), it panics with the raw error string. This is a hard panic, not a returned error, because the library assumes k8s capture only runs in-cluster.

Source

Thrown at internal/capture/capture.go:297

		defer close(err)
		if e := l.Listen(ctx); err != nil {
			err <- e
		}
	}()
	return err
}

// Allowed format:
//
//	[namespace/]pod/[pod_name]
//	[namespace/]deployment/[deployment_name]
//	[namespace/]daemonset/[daemonset_name]
//	[namespace/]labelSelector/[selector]
//	[namespace/]fieldSelector/[selector]
func k8sIPs(addr string) []string {
	config, err := rest.InClusterConfig()
	if err != nil {
		panic(err.Error())
	}

	// creates the clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	sections := strings.Split(addr, "/")

	if len(sections) < 2 {
		panic("Not supported k8s scheme. Allowed values: [namespace/]pod/[pod_name], [namespace/]deployment/[deployment_name], [namespace/]daemonset/[daemonset_name], [namespace/]label/[label-name]/[label-value]")
	}

	// If no namespace passed, assume it is ALL
	switch sections[0] {
	case "pod", "deployment", "daemonset", "labelSelector", "fieldSelector":
		sections = append([]string{""}, sections...)

View on GitHub (pinned to 251e45abd2)

Solutions

  1. Run the process inside the cluster with a service account (token at /var/run/secrets/kubernetes.io/serviceaccount).
  2. If running outside, use clientcmd kubeconfig loading instead of rest.InClusterConfig() before deciding the address is k8s.
  3. Enable automountServiceAccountToken and grant RBAC get/list on pods for the service account.
  4. Guard the call: only route addresses with a k8s scheme to k8sIPs; validate rest.InClusterConfig() error and fall back gracefully instead of panicking.

Example fix

// before
config, err := rest.InClusterConfig()
if err != nil {
	panic(err.Error())
}
// after
config, err := rest.InClusterConfig()
if err != nil {
	return nil, fmt.Errorf("k8s capture requires in-cluster config: %w", err)
}
Defensive patterns

Strategy: fallback

Validate before calling

func inCluster() bool {
	_, err := os.Stat("/var/run/secrets/kubernetes.io/serviceaccount/token")
	return err == nil && os.Getenv("KUBERNETES_SERVICE_HOST") != ""
}

Try / catch

if inCluster() {
	ips = k8sIPs(addr)
} else {
	return fmt.Errorf("k8s capture address %q requires running in-cluster (service account missing)", addr)
}

Prevention

When it happens

Trigger: Calling NewListener with a k8s address (e.g. 'default/pod/my-pod') from a process outside a cluster — local dev, CI, docker without a mounted service account, or with KUBERNETES_SERVICE_HOST unset.

Common situations: Testing k8s capture flags locally; running the binary in plain Docker; the service account token volume not mounted (automountServiceAccountToken: false); kubeconfig present in ~/.kube but in-cluster config not used.

Related errors


AI-assisted analysis of probelabs/goreplay@251e45abd2 (2026-09-02). Data as JSON: /api/errors/273f173f27149baa. Report an issue: GitHub.