{"record":{"id":"eae607950f9c092e","repo":"apache/seatunnel","slug":"parameter-pluginname-cannot-be-empty","errorCode":null,"errorMessage":"Parameter 'pluginName' cannot be empty.","messagePattern":"Parameter 'pluginName' cannot be empty\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/OptionRulesService.java","lineNumber":217,"sourceCode":"        }\n        if (StringUtils.equalsIgnoreCase(normalizedPluginType, PluginType.SINK.getType())) {\n            return PluginType.SINK;\n        }\n        if (StringUtils.equalsIgnoreCase(normalizedPluginType, PluginType.TRANSFORM.getType())) {\n            return PluginType.TRANSFORM;\n        }\n        throw new IllegalArgumentException(\n                String.format(\n                        \"Unsupported plugin type '%s'. Only '%s', '%s' and '%s' are supported.\",\n                        normalizedPluginType,\n                        PluginType.SOURCE.getType(),\n                        PluginType.SINK.getType(),\n                        PluginType.TRANSFORM.getType()));\n    }\n\n    private String normalizePluginName(String pluginName) {\n        if (StringUtils.isBlank(pluginName)) {\n            throw new IllegalArgumentException(\n                    String.format(\"Parameter '%s' cannot be empty.\", PARAM_PLUGIN));\n        }\n        return pluginName.trim().toLowerCase(Locale.ROOT);\n    }\n\n    private OptionRuleResponse.RequiredOptionMetadata toRequiredOptionMetadata(\n            RequiredOption requiredOption) {\n        List<OptionRuleResponse.OptionMetadata> options =\n                requiredOption.getOptions().stream()\n                        .map(this::toOptionMetadata)\n                        .collect(Collectors.toList());\n        OptionRuleResponse.RuleType ruleType = resolveRuleType(requiredOption);\n        if (ruleType == null) {\n            throw new IllegalArgumentException(\n                    String.format(\n                            \"Unsupported required option type: %s\",\n                            requiredOption.getClass().getName()));\n        }","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/OptionRulesService.java#L199-L235","documentation":"OptionRulesService.normalizePluginName validates the pluginName path/query parameter used when looking up connector option rules. If the value is blank (null, empty, or whitespace-only) it throws IllegalArgumentException naming the parameter. The service requires a concrete plugin (source/sink/transform) name to resolve its OptionRule.","triggerScenarios":"Calling the REST option-rules endpoint (e.g. /option-rules/<pluginName>) with an empty path segment, a bare trailing slash, or a blank 'pluginName' query parameter.","commonSituations":"Client code builds the URL with an unset/empty variable; a proxy strips the path suffix; an upstream template renders ${plugin} as empty; manual curl invocation like GET /option-rules/ without a plugin name.","solutions":["Pass a valid, non-blank plugin name in the URL or query parameter, e.g. /option-rules/FakeSource","Trim user input client-side and reject blank values before calling the endpoint","Use one of the supported plugin types (source/sink/transform plugin identifiers) that actually exist","Return a 400 response with this message instead of a 500 from the generic exception handler"],"exampleFix":"// before\nString url = base + \"/option-rules/\" + pluginName; // pluginName is \"\"\n// after\nif (pluginName == null || pluginName.isBlank()) {\n    throw new IllegalArgumentException(\"pluginName must be provided\");\n}\nString url = base + \"/option-rules/\" + pluginName.trim().toLowerCase(Locale.ROOT);","handlingStrategy":"validation","validationCode":"if (pluginName == null || pluginName.isBlank()) throw new IllegalArgumentException(\"pluginName required\");\nString normalized = pluginName.trim().toLowerCase(Locale.ROOT);","typeGuard":"boolean isValidPluginName(String s) { return s != null && !s.isBlank(); }","tryCatchPattern":"try { callOptionRules(name); } catch (IllegalArgumentException e) { return 400; }","preventionTips":["Always URL-encode and trim the plugin name","Validate non-blank input at the API client boundary","Use constants for supported plugin names"],"tags":["rest","validation","illegal-argument"],"backgroundTag":"empty-required-field","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}