Skip to content

[BUG]CacheRuntime controller panics with nil pointer dereference when client component is not defined in CacheRuntimeClass topology #6147

Description

@btxu-db

What is your environment(Kubernetes version, Fluid version, etc.)
k8s version: 1.36.1-aliyun.1
fluid version: 1.1.0-alpha.11
Describe the bug
When the client component is not defined in the topology of a CacheRuntimeClass, generateRuntimeConfigData panics with a nil pointer dereference, causing the cacheruntime-controller pod to crash and restart.
The error message is as follows:

kubectl logs -n fluid-system cacheruntime-controller-868f9494b4-46xp8 --previous
2026/08/03 17:18:24 nodeExcludeSelector is empty, no node would be excluded when syncing schedule info of runtimes
2026/08/03 17:18:24 BuildDate: 2026-07-12_09:41:07
2026/08/03 17:18:24 GitCommit: 676f47a841133ba9ffcaafe9c76b44b2cb6b11a9
2026/08/03 17:18:24 GitTreeState: dirty
2026/08/03 17:18:24 GoVersion: go1.25.12
2026/08/03 17:18:24 Compiler: gc
2026/08/03 17:18:24 Platform: linux/amd64
2026-08-03T17:18:24.423+0800    INFO    setup   utils/pprof.go:33       Enabling pprof  {"pprof address": ":6060"}
2026-08-03T17:18:24.423+0800    INFO    setup   utils/pprof.go:48       Starting pprof HTTP server      {"pprof server address": ":6060"}
2026-08-03T17:18:24.438+0800    INFO    setup   app/cache.go:143        AdvancedStatefulSet controller added successfully
2026-08-03T17:18:24.438+0800    INFO    dump    dump/dump.go:61 Register goroutine dump generator
2026-08-03T17:18:24.438+0800    INFO    setup   app/cache.go:171        starting cacheruntime-controller
2026-08-03T17:18:24.439+0800    INFO    controller-runtime.metrics      server/server.go:205    Starting metrics server
2026-08-03T17:18:24.439+0800    INFO    controller-runtime.metrics      server/server.go:244    Serving metrics server  {"bindAddress": ":8080", "secure": false}
I0803 17:18:24.539967       1 leaderelection.go:250] attempting to acquire leader lease fluid-system/cache.data.fluid.io...
I0803 17:18:42.443670       1 leaderelection.go:260] successfully acquired lease fluid-system/cache.data.fluid.io
2026-08-03T17:18:42.444+0800    INFO    controller/controller.go:178    Starting EventSource    {"controller": "advancedstatefulset-controller", "source": "kind source: *v1alpha1.AdvancedStatefulSet"}
2026-08-03T17:18:42.444+0800    INFO    controller/controller.go:178    Starting EventSource    {"controller": "advancedstatefulset-controller", "source": "kind source: *v1.PersistentVolumeClaim"}
2026-08-03T17:18:42.444+0800    INFO    controller/controller.go:178    Starting EventSource    {"controller": "advancedstatefulset-controller", "source": "kind source: *v1.Pod"}
2026-08-03T17:18:42.444+0800    INFO    controller/controller.go:186    Starting Controller     {"controller": "advancedstatefulset-controller"}
2026-08-03T17:18:42.444+0800    INFO    controller/controller.go:178    Starting EventSource    {"controller": "CacheRuntimeController", "source": "kind source: *v1alpha1.CacheRuntime"}
2026-08-03T17:18:42.444+0800    INFO    controller/controller.go:178    Starting EventSource    {"controller": "CacheRuntimeController", "source": "kind source: *v1alpha1.AdvancedStatefulSet"}
2026-08-03T17:18:42.444+0800    INFO    controller/controller.go:178    Starting EventSource    {"controller": "CacheRuntimeController", "source": "kind source: *v1.DaemonSet"}
2026-08-03T17:18:42.444+0800    INFO    controller/controller.go:186    Starting Controller     {"controller": "CacheRuntimeController"}
2026-08-03T17:18:42.546+0800    INFO    controller/controller.go:220    Starting workers        {"controller": "advancedstatefulset-controller", "worker count": 3}
I0803 17:18:42.546842       1 statefulset_controller.go:243] "AdvancedStatefulSet deleted" statefulSet="default/mooncake-demo-master"
I0803 17:18:42.546862       1 statefulset_controller.go:243] "AdvancedStatefulSet deleted" statefulSet="default/mooncake-demo-worker"
I0803 17:18:42.546903       1 statefulset_controller.go:233] "Finished syncing AdvancedStatefulSet" statefulSet="default/mooncake-demo-worker" elapsedTime="85.875µs"
I0803 17:18:42.546869       1 statefulset_controller.go:233] "Finished syncing AdvancedStatefulSet" statefulSet="default/mooncake-demo-master" elapsedTime="53.418µs"
2026-08-03T17:18:42.547+0800    INFO    controller/controller.go:220    Starting workers        {"controller": "CacheRuntimeController", "worker count": 3}
2026-08-03T17:18:42.547+0800    INFO    cachectl.CacheRuntime   engine/engine.go:100    Set the syncRetryDuration       {"cacheRuntime": {"name":"mooncake-demo","namespace":"default"}, "cache engine": "cache", "id": "default-mooncake-demo", "syncRetryDuration": 15}
2026-08-03T17:18:42.749+0800    INFO    cachectl.CacheRuntime   engine/util.go:56       mountRoot       {"cacheRuntime": {"name":"mooncake-demo","namespace":"default"}, "cache engine": "cache", "id": "default-mooncake-demo", "path": "/runtime-mnt/cache"}
2026-08-03T17:18:42.749+0800    INFO    cachectl.CacheRuntime   engine/util.go:56       mountRoot       {"cacheRuntime": {"name":"mooncake-demo","namespace":"default"}, "cache engine": "cache", "id": "default-mooncake-demo", "path": "/runtime-mnt/cache"}
2026-08-03T17:18:42.850+0800    INFO    cachectl.CacheRuntime   engine/util.go:56       mountRoot       {"cacheRuntime": {"name":"mooncake-demo","namespace":"default"}, "cache engine": "cache", "id": "default-mooncake-demo", "path": "/runtime-mnt/cache"}
2026-08-03T17:18:42.850+0800    INFO    controller/controller.go:115    Observed a panic in reconciler: runtime error: invalid memory address or nil pointer dereference        {"controller": "CacheRuntimeController", "object": {"name":"mooncake-demo","namespace":"default"}, "namespace": "default", "name": "mooncake-demo", "reconcileID": "e3fc461b-2938-4b8a-ba9d-cc640297d2fd"}
panic: runtime error: invalid memory address or nil pointer dereference [recovered, repanicked]
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x22bc421]

goroutine 211 [running]:
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Reconcile.func1()
        /go/src/github.com/fluid-cloudnative/fluid/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:116 +0x2cd
panic({0x285a600?, 0x3be7750?})
        /usr/local/go/src/runtime/panic.go:783 +0x136
github.com/fluid-cloudnative/fluid/pkg/ddc/cache/engine.(*CacheEngine).generateRuntimeConfigData(0xc0009f0900, {0x2d6a220, 0xc0009f0cc0}, 0xc000adcc08)
        /go/src/github.com/fluid-cloudnative/fluid/pkg/ddc/cache/engine/cm.go:178 +0xf81
github.com/fluid-cloudnative/fluid/pkg/ddc/cache/engine.(*CacheEngine).createRuntimeValueConfigMap(0xc0009f0900, {0x2d6a220, 0xc0009f0cc0}, 0xc000adcc08, {0xc000493ea0, 0x1, 0x1})
        /go/src/github.com/fluid-cloudnative/fluid/pkg/ddc/cache/engine/cm.go:93 +0x20b
github.com/fluid-cloudnative/fluid/pkg/ddc/cache/engine.(*CacheEngine).createRuntimeConfigMaps(0xc0009f0900, {0x2d6a220, 0xc0009f0cc0}, 0xc0004ebce0)
        /go/src/github.com/fluid-cloudnative/fluid/pkg/ddc/cache/engine/cm.go:57 +0x34f
github.com/fluid-cloudnative/fluid/pkg/ddc/cache/engine.(*CacheEngine).Setup(0xc0009f0900, {{0x2d6a5d8, 0xc0001776c0}, {{0xc0009c0226, 0x7}, {0xc0009c0230, 0xd}}, {0x2b418b2, 0xa}, 0xc000942008, ...})
        /go/src/github.com/fluid-cloudnative/fluid/pkg/ddc/cache/engine/setup.go:50 +0x405
github.com/fluid-cloudnative/fluid/pkg/controllers.(*RuntimeReconciler).ReconcileRuntime(0xc000360370, {0x2d6fe88, 0xc0009f0900}, {{0x2d6a5d8, 0xc0001776c0}, {{0xc0009c0226, 0x7}, {0xc0009c0230, 0xd}}, {0x2b418b2, ...}, ...})
        /go/src/github.com/fluid-cloudnative/fluid/pkg/controllers/runtime_controller.go:272 +0x57c
github.com/fluid-cloudnative/fluid/pkg/controllers.(*RuntimeReconciler).ReconcileInternal(0xc000360370, {{0x2d6a5d8, 0xc0001776c0}, {{0xc0009c0226, 0x7}, {0xc0009c0230, 0xd}}, {0x2b418b2, 0xa}, 0xc000942008, ...})
        /go/src/github.com/fluid-cloudnative/fluid/pkg/controllers/runtime_controller.go:181 +0x13bf
github.com/fluid-cloudnative/fluid/pkg/controllers/v1alpha1/cacheruntime.(*CacheRuntimeReconciler).Reconcile(0xc00032ede0, {0x2d6a530, 0xc000a88b40}, {{{0xc0009c0226, 0x7}, {0xc0009c0230, 0xd}}})
        /go/src/github.com/fluid-cloudnative/fluid/pkg/controllers/v1alpha1/cacheruntime/cacheruntime_controller.go:120 +0xb58
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Reconcile(0xc0002d0c80, {0x2d6a530, 0xc000a88b40}, {{{0xc0009c0226, 0x7}, {0xc0009c0230, 0xd}}})
        /go/src/github.com/fluid-cloudnative/fluid/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:119 +0x15b
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler(0xc0002d0c80, {0x2d6a530, 0xc000a88b40}, {0x294e800, 0xc0004b41c0})
        /go/src/github.com/fluid-cloudnative/fluid/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:316 +0x44d
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem(0xc0002d0c80, {0x2d6a568, 0xc000286230})
        /go/src/github.com/fluid-cloudnative/fluid/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:266 +0x359
sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2()
        /go/src/github.com/fluid-cloudnative/fluid/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:227 +0xac
created by sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2 in goroutine 120
        /go/src/github.com/fluid-cloudnative/fluid/vendor/sigs.k8s.io/controller-runtime/pkg/internal/controller/controller.go:223 +0x927

What you expect to happen:
I expect that when the client component is not defined in a CacheRuntimeClass, the controller should either treat the client component as disabled and continue reconciling normally, or reject the resource with a clear validation error — instead of crashing with a panic.
**How to reproduce **

1.Create a CacheRuntimeClass that defines only master and worker components in topology — the client component is intentionally omitted. Then create a Dataset and CacheRuntime.
Note: whether the CacheRuntime spec contains a client field does not affect this bug — the panic occurs either way. The trigger is the missing client component in the CacheRuntimeClass topology:
dataset-runtime.yaml:

apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
  name: mooncake-demo
  namespace: default
spec:
  placement: Shared
  accessModes:
    - ReadWriteMany
  mounts:
    - name: mc
      mountPoint: "mooncakefs:///"
---
apiVersion: data.fluid.io/v1alpha1
kind: CacheRuntime
metadata:
  name: mooncake-demo
  namespace: default
spec:
  runtimeClassName: mooncake-demo
  master:
    replicas: 1
  worker:
    replicas: 2
    tieredStore:
      levels:
        - emptyDir:
            quota: 1Gi
          high: "0.8"
          low: "0.5"

cacheruntimeclass.yaml:

apiVersion: data.fluid.io/v1alpha1
kind: CacheRuntimeClass
metadata:
  name: mooncake-demo
fileSystemType: mooncakefs
topology:
  master:
    service:
      headless: {}
    template:
      spec:
        restartPolicy: Always
        containers:
          - name: master
            image: crpi-4hkqof7tc9brc6d5.cn-hongkong.personal.cr.aliyuncs.com/mooncake1314/mooncake:v2
            command:
              - /custom-entrypoint.sh
            args:
              - master
              - start
            imagePullPolicy: IfNotPresent
            readinessProbe:
              tcpSocket:
                port: 50051
              initialDelaySeconds: 10
              periodSeconds: 5
              failureThreshold: 12
            env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
            ports:
              - containerPort: 50051
                name: rpc
              - containerPort: 8080
                name: metadata
              - containerPort: 9003
                name: metrics
  worker:
    service:
      headless: {}
    template:
      spec:
        restartPolicy: Always
        containers:
          - name: worker
            image: crpi-4hkqof7tc9brc6d5.cn-hongkong.personal.cr.aliyuncs.com/mooncake1314/mooncake:v2
            command:
              - /custom-entrypoint.sh
            args:
              - worker
              - start
            imagePullPolicy: IfNotPresent
            readinessProbe:
              tcpSocket:
                port: 50052
              initialDelaySeconds: 5
              periodSeconds: 5
              failureThreshold: 12
            env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
            ports:
              - containerPort: 50052
                name: data
              - containerPort: 9300
                name: http   
  1. Apply it:
kubectl apply -f cacheruntimeclass.yaml
kubectl apply -f dataset-runtime.yaml
  1. Observe the cacheruntime-controller pod:
kubectl get pods -n fluid-system -w

The controller pod crashes and restarts:

NAME                                       READY   STATUS             RESTARTS      AGE
cacheruntime-controller-868f9494b4-46xp8   1/1     Running            1 (2s ago)    6m10s
cacheruntime-controller-868f9494b4-46xp8   0/1     Error              1 (20s ago)   6m28s
cacheruntime-controller-868f9494b4-46xp8   0/1     CrashLoopBackOff   1 (12s ago)   6m39s
cacheruntime-controller-868f9494b4-46xp8   1/1     Running            2 (12s ago)   6m39s
  1. Check the panic stack trace in the previous container's logs:
kubectl logs -n fluid-system <cacheruntime-controller-pod-name> --previous

The panic stack trace shown at the top of this issue can be found there.
Additional Information
Note: the container image and entrypoint script are irrelevant to this bug — the controller panics during ConfigMap generation, before any pod is scheduled. Any placeholder image works for reproduction.
Defining a client component in the CacheRuntimeClass topology avoids the panic:

  client:
    template:
      spec:
        restartPolicy: Always
        containers:
          - name: client
            image: <your-image>
            command:
              - /custom-entrypoint.sh
            args:
              - client
              - start
            imagePullPolicy: IfNotPresent
            securityContext:
              privileged: true
              runAsUser: 0

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions