apache/pulsar · error · RuntimeException

KubernetesSecretsProviderConfigurator should only be setup f

Error message

KubernetesSecretsProviderConfigurator should only be setup for Kubernetes Runtime

What it means

KubernetesSecretsProviderConfigurator implements SecretsProviderConfigurator but only supports the Kubernetes runtime. When the broker/function worker is configured with this configurator but a function is submitted to run as a process (or thread) runtime instead of Kubernetes, configureProcessRuntimeSecretsProvider is invoked and immediately throws this RuntimeException to signal the configurator is being used in an unsupported runtime mode.

Source

Thrown at pulsar-functions/secrets/src/main/java/org/apache/pulsar/functions/secretsproviderconfigurator/KubernetesSecretsProviderConfigurator.java:106

            Map<String, Object> secretsMap = new Gson().fromJson(functionDetails.getSecretsMap(), type);
            for (Map.Entry<String, Object> entry : secretsMap.entrySet()) {
                final V1EnvVar secretEnv = new V1EnvVar();
                @SuppressWarnings("unchecked") // secret values are expected to be Map<String, String>
                Map<String, String> kv = (Map<String, String>) entry.getValue();
                secretEnv.name(entry.getKey())
                        .valueFrom(new V1EnvVarSource()
                                .secretKeyRef(new V1SecretKeySelector()
                                        .name(kv.get(idKey))
                                        .key(kv.get(keyKey))));
                container.addEnvItem(secretEnv);
            }
        }
    }

    @Override
    public void configureProcessRuntimeSecretsProvider(ProcessBuilder processBuilder,
                                                       FunctionDetails functionDetails) {
        throw new RuntimeException("KubernetesSecretsProviderConfigurator should only be setup for Kubernetes Runtime");
    }

    @Override
    public Type getSecretObjectType() {
        return new TypeToken<Map<String, String>>() {
        }.getType();
    }

    // The secret object should be of type Map<String, String> and it should contain "id" and "key"
    @Override
    public void doAdmissionChecks(AppsV1Api appsV1Api, CoreV1Api coreV1Api, String jobNamespace, String jobName,
                                  FunctionDetails functionDetails) {
        if (!StringUtils.isEmpty(functionDetails.getSecretsMap())) {
            Type type = new TypeToken<Map<String, Object>>() {
            }.getType();
            Map<String, Object> secretsMap = new Gson().fromJson(functionDetails.getSecretsMap(), type);

            for (Object object : secretsMap.values()) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Set functions runtime to 'kubernetes' in functions_worker.yml (functionsWorkerCustomConfigs / overrideFunctionConfig) or submit the function with the kubernetes runtime so this method is never called
  2. Change worker's secretsProviderConfigurator to DefaultSecretsProviderConfigurator (or another process-runtime-compatible configurator) if functions must run as process/thread runtime
  3. Pass the secrets as plain config through a different SecretsProvider (e.g. ClearSecretsProvider) compatible with process runtimes

Example fix

// before (functions_worker.yml)
secretsProviderConfiguratorClassName: org.apache.pulsar.functions.secretsproviderconfigurator.KubernetesSecretsProviderConfigurator
functionsWorkerCustomConfigs:
  functionsRuntime: PROCESS
// after
secretsProviderConfiguratorClassName: org.apache.pulsar.functions.secretsproviderconfigurator.KubernetesSecretsProviderConfigurator
functionsWorkerCustomConfigs:
  functionsRuntime: KUBERNETES
# ...or keep PROCESS and switch to:
# secretsProviderConfiguratorClassName: org.apache.pulsar.functions.secretsproviderconfigurator.DefaultSecretsProviderConfigurator
Defensive patterns

Strategy: validation

Validate before calling

boolean usesK8sSecretsConfigurator = "org.apache.pulsar.functions.secretsproviderconfigurator.KubernetesSecretsProviderConfigurator"
        .equals(workerConfig.getSecretsProviderConfiguratorClassName());
boolean k8sRuntime = "KUBERNETES".equalsIgnoreCase(runtime);
if (usesK8sSecretsConfigurator && !k8sRuntime) {
    throw new IllegalStateException("KubernetesSecretsProviderConfigurator requires the Kubernetes runtime");
}

Type guard

static boolean isKubernetesRuntime(ObjectRuntimeConfig cfg) {
    return cfg != null && "KUBERNETES".equalsIgnoreCase(cfg.getRuntime());
}

Prevention

When it happens

Trigger: A function is submitted with functionConfig/exposed secrets while the worker's secretsProviderConfigurator class is set to KubernetesSecretsProviderConfigurator, but the function runs on the 'process' (or 'thread') runtime instead of the 'kubernetes' runtime, so the framework calls configureProcessRuntimeSecretsProvider.

Common situations: operators switch functions.runtime to 'process' in worker config (or submit a function with runtime override) while leaving secretsProviderConfigurator=org.apache.pulsar.functions.secretsproviderconfigurator.KubernetesSecretsProviderConfigurator in functions_worker.yml on a Kubernetes cluster; migration of functions from K8s runtime to process runtime without changing the secrets configurator.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/79ab7adb0dfa8037. Report an issue: GitHub.