dapr/dapr · critical

unable to get controller runtime configuration, err: %s

Error message

unable to get controller runtime configuration, err: %s

What it means

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.

Source

Thrown at pkg/operator/operator.go:111

type operator struct {
	apiServer api.Server

	config       *Config
	mgr          ctrl.Manager
	podMetaCache ctrlcache.Cache
	secProvider  security.Provider

	secHealthz       healthz.Target
	apiServerHealthz healthz.Target
	webhookHealthz   healthz.Target
	cacheHealthz     healthz.Target
}

// NewOperator returns a new Dapr Operator.
func NewOperator(ctx context.Context, opts Options) (Operator, error) {
	conf, err := ctrl.GetConfig()
	if err != nil {
		return nil, fmt.Errorf("unable to get controller runtime configuration, err: %s", err)
	}

	config, err := LoadConfiguration(ctx, opts.Config, conf)
	if err != nil {
		return nil, fmt.Errorf("unable to load configuration, config: %s, err: %w", opts.Config, err)
	}

	secProvider, err := security.New(ctx, security.Options{
		SentryAddress:           config.SentryAddress,
		ControlPlaneTrustDomain: config.ControlPlaneTrustDomain,
		ControlPlaneNamespace:   security.CurrentNamespace(),
		TrustAnchorsFile:        &opts.TrustAnchorsFile,
		AppID:                   "dapr-operator",
		// mTLS is always enabled for the operator.
		MTLSEnabled: true,
		Mode:        modes.KubernetesMode,
		Healthz:     opts.Healthz,
		// The operator serves CRD conversion / validating / mutating webhooks

View on GitHub (pinned to 74ad417027)

Solutions

  1. Outside Kubernetes: export KUBECONFIG=/path/to/kubeconfig (or place it at ~/.kube/config) pointing at the target cluster.
  2. In a pod: verify the pod has a service account and the env vars exist (kubectl exec deploy/dapr-operator -- env | grep KUBERNETES).
  3. Validate the kubeconfig itself: kubectl cluster-info --kubeconfig $KUBECONFIG.
  4. Check readability of /var/run/secrets/kubernetes.io/serviceaccount/token and of the kubeconfig file (permissions, mount path).

Example fix

# before
./operator --config daprsystem   # fails: no kubeconfig anywhere
# after
export KUBECONFIG=~/clusters/dev.yaml
./operator --config daprsystem
Defensive patterns

Strategy: validation

Validate before calling

import (
	"fmt"
	"os"
	"path/filepath"
)

// PrecheckKubeConfig reports whether ctrl.GetConfig() will find a usable source.
func PrecheckKubeConfig() error {
	if os.Getenv("KUBERNETES_SERVICE_HOST") != "" && os.Getenv("KUBERNETES_SERVICE_PORT") != "" {
		return nil // in-cluster config available
	}
	for _, p := range filepath.SplitList(os.Getenv("KUBECONFIG")) {
		if p == "" {
			continue
		}
		if _, err := os.Stat(p); err == nil {
			return nil
		}
	}
	home, _ := os.UserHomeDir()
	if _, err := os.Stat(filepath.Join(home, ".kube", "config")); err == nil {
		return nil
	}
	return fmt.Errorf("no kubeconfig source: set KUBECONFIG or run in-cluster")
}

Try / catch

op, err := operator.NewOperator(ctx, opts)
if err != nil {
	if strings.Contains(err.Error(), "unable to get controller runtime configuration") {
		// config-source problem: fix env/kubeconfig, not the cluster
		log.Fatalf("missing kube config: set KUBECONFIG or run inside a cluster: %v", err)
	}
	log.Fatalf("operator startup failed: %v", err)
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of dapr/dapr@74ad417027 (2026-08-16). Data as JSON: /api/errors/732f4934a575f2b3. Report an issue: GitHub.