{"record":{"id":"e4f2ed8324316fa9","repo":"apache/pulsar","slug":"function-config-is-not-provided","errorCode":null,"errorMessage":"Function config is not provided","messagePattern":"Function config is not provided","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java","lineNumber":92,"sourceCode":"        private String functionClassName;\n        private String typeArg0;\n        private String typeArg1;\n    }\n\n    static final Integer MAX_PENDING_ASYNC_REQUESTS_DEFAULT = 1000;\n    static final Boolean FORWARD_SOURCE_MESSAGE_PROPERTY_DEFAULT = Boolean.TRUE;\n\n    private static final ObjectMapper OBJECT_MAPPER = ObjectMapperFactory.create();\n\n    public static FunctionDetails convert(FunctionConfig functionConfig) {\n        return convert(functionConfig, (ValidatableFunctionPackage) null);\n    }\n\n    public static FunctionDetails convert(FunctionConfig functionConfig,\n                                          ValidatableFunctionPackage validatableFunctionPackage)\n            throws IllegalArgumentException {\n        if (functionConfig == null) {\n            throw new IllegalArgumentException(\"Function config is not provided\");\n        }\n        if (functionConfig.getRuntime() == FunctionConfig.Runtime.JAVA && validatableFunctionPackage != null) {\n            return convert(functionConfig, doJavaChecks(functionConfig, validatableFunctionPackage));\n        } else {\n            return convert(functionConfig, new ExtractedFunctionDetails(functionConfig.getClassName(), null, null));\n        }\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    public static FunctionDetails convert(FunctionConfig functionConfig, ExtractedFunctionDetails extractedDetails)\n             throws IllegalArgumentException {\n\n        boolean isBuiltin = !StringUtils.isEmpty(functionConfig.getJar())\n                && functionConfig.getJar().startsWith(org.apache.pulsar.common.functions.Utils.BUILTIN);\n\n        FunctionDetails functionDetails = new FunctionDetails();\n\n        // Setup source","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java#L74-L110","documentation":"FunctionConfigUtils.convert(FunctionConfig, ValidatableFunctionPackage) validates and transforms a user-supplied FunctionConfig into protobuf FunctionDetails. A null FunctionConfig cannot be converted, so it immediately throws this IllegalArgumentException.","triggerScenarios":"Calling convert(null, validatableFunctionPackage) or otherwise passing a null FunctionConfig reference — typically from a CLI/REST handler where the config object was never constructed, or a deserialization path that produced a null config.","commonSituations":"Programmatic function submission where FunctionConfig was left uninitialized; REST payloads that fail to bind into a FunctionConfig object; scripts that call the internal conversion API directly; refactored code paths that dropped config initialization.","solutions":["Construct and populate the FunctionConfig before calling convert (set tenant, namespace, name, className, inputs, runtime, etc.)","Check that your REST/CLI layer actually parses the submitted function configuration into a non-null FunctionConfig","Add a null check in your calling code and surface a clear client-facing validation error","If using the Java client, verify the config serialization/deserialization isn't dropping the functionConfig field"],"exampleFix":"// before\nFunctionConfig cfg = null;\nFunctionDetails d = FunctionConfigUtils.convert(cfg, pkg); // throws\n// after\nFunctionConfig cfg = new FunctionConfig();\ncfg.setTenant(\"public\"); cfg.setNamespace(\"default\"); cfg.setName(\"f\"); cfg.setClassName(\"com.ex.MyFn\");\nFunctionDetails d = FunctionConfigUtils.convert(cfg, pkg);","handlingStrategy":"validation","validationCode":"// Null-check before convert\nif (functionConfig == null) {\n  throw new IllegalArgumentException(\"functionConfig must be provided\");\n}\n// optionally also verify required fields\nif (functionConfig.getClassName() == null || functionConfig.getTenant() == null) {\n  throw new IllegalArgumentException(\"functionConfig incomplete\");\n}","typeGuard":"static boolean hasConfig(FunctionConfig cfg) { return cfg != null; }","tryCatchPattern":"try {\n  FunctionDetails d = FunctionConfigUtils.convert(cfg, pkg);\n} catch (IllegalArgumentException e) {\n  if (\"Function config is not provided\".equals(e.getMessage())) {\n    log.error(\"No FunctionConfig supplied - check request binding\");\n    throw new BadRequestException(\"functionConfig is required\");\n  }\n  throw e;\n}","preventionTips":["Initialize FunctionConfig in constructors/DSL builders before submission","Validate REST payload binding produces a non-null config","Add a fail-fast null check at your API entry point","Use Objects.requireNonNull(cfg, ...) in your wrapper code"],"tags":["pulsar-functions","null-check","configuration","validation"],"backgroundTag":"missing-required-config","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"}