{"record":{"id":"732f4934a575f2b3","repo":"dapr/dapr","slug":"unable-to-get-controller-runtime-configuration-er","errorCode":null,"errorMessage":"unable to get controller runtime configuration, err: %s","messagePattern":"unable to get controller runtime configuration, err: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/operator/operator.go","lineNumber":111,"sourceCode":"type operator struct {\n\tapiServer api.Server\n\n\tconfig       *Config\n\tmgr          ctrl.Manager\n\tpodMetaCache ctrlcache.Cache\n\tsecProvider  security.Provider\n\n\tsecHealthz       healthz.Target\n\tapiServerHealthz healthz.Target\n\twebhookHealthz   healthz.Target\n\tcacheHealthz     healthz.Target\n}\n\n// NewOperator returns a new Dapr Operator.\nfunc NewOperator(ctx context.Context, opts Options) (Operator, error) {\n\tconf, err := ctrl.GetConfig()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to get controller runtime configuration, err: %s\", err)\n\t}\n\n\tconfig, err := LoadConfiguration(ctx, opts.Config, conf)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to load configuration, config: %s, err: %w\", opts.Config, err)\n\t}\n\n\tsecProvider, err := security.New(ctx, security.Options{\n\t\tSentryAddress:           config.SentryAddress,\n\t\tControlPlaneTrustDomain: config.ControlPlaneTrustDomain,\n\t\tControlPlaneNamespace:   security.CurrentNamespace(),\n\t\tTrustAnchorsFile:        &opts.TrustAnchorsFile,\n\t\tAppID:                   \"dapr-operator\",\n\t\t// mTLS is always enabled for the operator.\n\t\tMTLSEnabled: true,\n\t\tMode:        modes.KubernetesMode,\n\t\tHealthz:     opts.Healthz,\n\t\t// The operator serves CRD conversion / validating / mutating webhooks","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/dapr/dapr/blob/74ad41702745709bb15fe2114ff693b8c59bc3cc/pkg/operator/operator.go#L93-L129","documentation":"NewOperator calls controller-runtime's ctrl.GetConfig() to resolve a Kubernetes *rest.Config. GetConfig tries in-cluster config first (KUBERNETES_SERVICE_HOST/PORT env vars plus the mounted service-account token), then falls back to $KUBECONFIG or ~/.kube/config. The error means none of these sources produced a usable config: not running in a pod, no kubeconfig file, or a malformed/unreadable one, so the Dapr Operator cannot build any Kubernetes client and aborts startup.","triggerScenarios":"Running the dapr-operator binary outside a pod with KUBECONFIG unset and no ~/.kube/config; $KUBECONFIG pointing at a deleted or invalid YAML file; a pod whose service-account token volume or KUBERNETES_SERVICE_HOST/KUBERNETES_SERVICE_PORT env vars were stripped (e.g., by a mutated pod spec or bare pod template).","commonSituations":"Local debugging of the operator against kind/minikube without exporting a kubeconfig; CI pipelines that execute the binary with no cluster credentials; hardened base images that omit the service-account mount.","solutions":["Outside Kubernetes: export KUBECONFIG=/path/to/kubeconfig (or place it at ~/.kube/config) pointing at the target cluster.","In a pod: verify the pod has a service account and the env vars exist (kubectl exec deploy/dapr-operator -- env | grep KUBERNETES).","Validate the kubeconfig itself: kubectl cluster-info --kubeconfig $KUBECONFIG.","Check readability of /var/run/secrets/kubernetes.io/serviceaccount/token and of the kubeconfig file (permissions, mount path)."],"exampleFix":"# before\n./operator --config daprsystem   # fails: no kubeconfig anywhere\n# after\nexport KUBECONFIG=~/clusters/dev.yaml\n./operator --config daprsystem","handlingStrategy":"validation","validationCode":"import (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n)\n\n// PrecheckKubeConfig reports whether ctrl.GetConfig() will find a usable source.\nfunc PrecheckKubeConfig() error {\n\tif os.Getenv(\"KUBERNETES_SERVICE_HOST\") != \"\" && os.Getenv(\"KUBERNETES_SERVICE_PORT\") != \"\" {\n\t\treturn nil // in-cluster config available\n\t}\n\tfor _, p := range filepath.SplitList(os.Getenv(\"KUBECONFIG\")) {\n\t\tif p == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif _, err := os.Stat(p); err == nil {\n\t\t\treturn nil\n\t\t}\n\t}\n\thome, _ := os.UserHomeDir()\n\tif _, err := os.Stat(filepath.Join(home, \".kube\", \"config\")); err == nil {\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"no kubeconfig source: set KUBECONFIG or run in-cluster\")\n}","typeGuard":null,"tryCatchPattern":"op, err := operator.NewOperator(ctx, opts)\nif err != nil {\n\tif strings.Contains(err.Error(), \"unable to get controller runtime configuration\") {\n\t\t// config-source problem: fix env/kubeconfig, not the cluster\n\t\tlog.Fatalf(\"missing kube config: set KUBECONFIG or run inside a cluster: %v\", err)\n\t}\n\tlog.Fatalf(\"operator startup failed: %v\", err)\n}","preventionTips":["Always export KUBECONFIG explicitly in scripts/CI that run control-plane binaries outside a cluster.","For local operator runs, target a kind/minikube kubeconfig and never rely on ambient defaults.","In-cluster, keep the service-account token mount and KUBERNETES_* env vars intact in the pod spec."],"tags":["kubernetes","configuration","operator","startup","kubeconfig"],"backgroundTag":null,"analyzedSha":"74ad41702745709bb15fe2114ff693b8c59bc3cc","analyzedAt":"2026-08-16T04:22:26.543Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}