{"record":{"id":"b5adb0fc12d4e0de","repo":"crowdsecurity/crowdsec","slug":"kubernetes-client-is-not-initialized","errorCode":null,"errorMessage":"kubernetes client is not initialized","messagePattern":"kubernetes client is not initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/kubernetes/run.go","lineNumber":191,"sourceCode":"\t\ts.stopPods()\n\t\twg.Wait()\n\t\treturn watchErr\n\t}\n\ts.stopPods()\n\twg.Wait()\n\n\treturn nil\n}\n\nfunc (s *Source) Dump() any {\n\treturn s\n}\n\nfunc (s *Source) followPodLogs(ctx context.Context, ns string, pod string, container string, out chan pipeline.Event,\n\tonLineFunc func(string, string, chan pipeline.Event) error) error {\n\tclient := s.client\n\tif client == nil {\n\t\treturn errors.New(\"kubernetes client is not initialized\")\n\t}\n\n\t// TailLines: 0 means \"no historical catch-up, only new lines from now on\".\n\t// Unlike SinceTime, this stays correct across reconnects: a fixed SinceTime\n\t// would cause every retry to re-stream everything since the original call.\n\ttailLines := int64(0)\n\treq := client.CoreV1().Pods(ns).GetLogs(pod, &corev1.PodLogOptions{\n\t\tContainer:  container,\n\t\tFollow:     true,\n\t\tTimestamps: false,\n\t\tTailLines:  &tailLines,\n\t})\n\tfn := func() error {\n\t\tif err := ctx.Err(); err != nil {\n\t\t\treturn nil\n\t\t}\n\t\tstream, err := req.Stream(ctx)\n\t\tif err != nil {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/kubernetes/run.go#L173-L209","documentation":"followPodLogs reads the Kubernetes client from the Source and returns this error when the client is nil, i.e. Configure() was never called (or failed to initialize the clientset) before log tailing was attempted. It is an internal state guard preventing a nil-pointer panic inside the Kubernetes API calls.","triggerScenarios":"Calling followPodLogs (directly in tests, or via the source's run path) on a Source whose s.client is nil — typically when Configure was skipped or its error ignored.","commonSituations":"Tests constructing a Source manually without calling Configure; in production, an earlier failed Kubernetes API client init (bad kubeconfig, no in-cluster service account) whose error was swallowed before tailing started.","solutions":["Ensure Source.Configure() is called and its error checked before running the acquisition.","Fix the underlying client initialization failure (valid kubeconfig path, or proper in-cluster environment/ServiceAccount).","In tests, inject a fake clientset into s.client before invoking followPodLogs."],"exampleFix":"// before\nsrc := kubernetes.Source{}\nsrc.followPodLogs(ctx, ...)\n\n// after\nvar src kubernetes.Source\nif err := src.Configure(ctx, cfg, logger, metrics.AcquisitionMetricsLevelNone); err != nil {\n    log.Fatal(err)\n}\nsrc.followPodLogs(ctx, ...)","handlingStrategy":"type-guard","validationCode":"if src.Client == nil {\n    return fmt.Errorf(\"kubernetes source not configured: call Configure() first\")\n}","typeGuard":"func clientReady(s *kubernetes.Source) bool { return s.Client != nil }","tryCatchPattern":null,"preventionTips":["Always call Configure() and check its error before starting acquisition.","Construct sources through the standard acquisition pipeline instead of by hand in tests.","In tests, inject a fake clientset before calling methods that use the client."],"tags":["kubernetes","client-initialization","nil-check","lifecycle"],"backgroundTag":"module-init-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}