{"record":{"id":"2438be9f770650ec","repo":"apache/pulsar","slug":"function-authentication-provider-s-must-implement","errorCode":null,"errorMessage":"Function authentication provider %s must implement KubernetesFunctionAuthProvider","messagePattern":"Function authentication provider (.+?) must implement KubernetesFunctionAuthProvider","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntimeFactory.java","lineNumber":247,"sourceCode":"        // make sure the provided class is a kubernetes auth provider, this needs to run before the authProvider!\n        if (runtimeCustomizer.isPresent()) {\n            if (!(runtimeCustomizer.get() instanceof KubernetesManifestCustomizer)) {\n                throw new IllegalArgumentException(\"Function runtime customizer \"\n                        + runtimeCustomizer.get().getClass().getName()\n                        + \" must implement KubernetesManifestCustomizer\");\n            } else {\n                KubernetesManifestCustomizer manifestCustomizer =\n                        (KubernetesManifestCustomizer) runtimeCustomizer.get();\n                this.manifestCustomizer = Optional.of(manifestCustomizer);\n            }\n        } else {\n            this.manifestCustomizer = Optional.empty();\n        }\n\n        // make sure the provided class is a kubernetes auth provider\n        if (functionAuthProvider.isPresent()) {\n            if (!(functionAuthProvider.get() instanceof KubernetesFunctionAuthProvider)) {\n                throw new IllegalArgumentException(\"Function authentication provider \"\n                        + functionAuthProvider.get().getClass().getName()\n                        + \" must implement KubernetesFunctionAuthProvider\");\n            } else {\n                KubernetesFunctionAuthProvider kubernetesFunctionAuthProvider =\n                        (KubernetesFunctionAuthProvider) functionAuthProvider.get();\n                kubernetesFunctionAuthProvider.initialize(coreClient, serverCaBytes,\n                        (funcDetails) -> getRuntimeCustomizer()\n                                .map((customizer) -> customizer.customizeNamespace(funcDetails, jobNamespace))\n                                .orElse(jobNamespace), factoryConfig.getKubernetesFunctionAuthProviderConfig());\n                this.authProvider = Optional.of(kubernetesFunctionAuthProvider);\n            }\n        } else {\n            this.authProvider = Optional.empty();\n        }\n\n        this.grpcPort = factoryConfig.getGrpcPort();\n        this.metricsPort = factoryConfig.getMetricsPort();\n        this.narExtractionDirectory = factoryConfig.getNarExtractionDirectory();","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/kubernetes/KubernetesRuntimeFactory.java#L229-L265","documentation":"KubernetesRuntimeFactory.initialize validates that the configured function authentication provider implements KubernetesFunctionAuthProvider. The check runs before the provider is initialized with the Kubernetes core client and server CA, failing fast with IllegalArgumentException if the class is not a Kubernetes auth provider.","triggerScenarios":"Setting k8s function auth provider class (functionAuthProvider config) to a class that does not implement KubernetesFunctionAuthProvider; the instanceof check at line 247 fails during worker initialization when authentication is enabled on the Kubernetes runtime.","commonSituations":"Configuring a generic Pulsar client AuthPlugin class instead of the Kubernetes-specific provider; custom auth plugin built against an older Pulsar interface; copy-paste of class name from broker auth config; missing recompilation after a Pulsar upgrade.","solutions":["Make the configured provider class implement KubernetesFunctionAuthProvider (with initialize/configureAuthenticationConfig methods).","Point the auth provider config at org.apache.pulsar.functions.auth.KubernetesFunctionAuthProvider implementations (e.g. KubernetesSecretsTokenAuthProvider).","Rebuild the custom auth plugin against the deployed Pulsar version's API.","Disable the k8s function auth provider config if Kubernetes-level function auth is not needed."],"exampleFix":"// before\npublic class MyAuthProvider implements AuthenticationDataProvider { ... }\n// after\npublic class MyAuthProvider implements KubernetesFunctionAuthProvider { ... }","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(configuredAuthProviderClassName);\nif (!KubernetesFunctionAuthProvider.class.isAssignableFrom(c)) {\n    throw new IllegalArgumentException(configuredAuthProviderClassName + \" must implement KubernetesFunctionAuthProvider\");\n}","typeGuard":"boolean isValidAuthProvider(Object o) { return o instanceof KubernetesFunctionAuthProvider; }","tryCatchPattern":"try { factory.initialize(...); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"KubernetesFunctionAuthProvider\")) { log.fatal(\"Bad auth provider config\"); } throw e; }","preventionTips":["Do not reuse broker/client AuthPlugin classes as the k8s function auth provider","Rebuild custom auth plugins on Pulsar upgrades","Validate auth provider config with a startup test before production rollout"],"tags":["kubernetes","authentication","configuration","type-mismatch"],"backgroundTag":"class-does-not-implement-interface","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}