apache/seatunnel · error · IllegalArgumentException

Unsupported plugin type '${pluginType}'. Only 'source', 'sin

Error message

Unsupported plugin type '${pluginType}'. Only 'source', 'sink' and 'transform' are supported.

What it means

After trimming the 'type' parameter, parseSupportedPluginType matches it case-insensitively against the supported values source, sink, and transform. Any other value falls through and throws this IllegalArgumentException enumerating the only accepted values.

Source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/OptionRulesService.java:206

                });
    }

    private PluginType parseSupportedPluginType(String pluginTypeText) {
        if (StringUtils.isBlank(pluginTypeText)) {
            throw new IllegalArgumentException(
                    String.format("Parameter '%s' cannot be empty.", PARAM_TYPE));
        }
        String normalizedPluginType = pluginTypeText.trim();
        if (StringUtils.equalsIgnoreCase(normalizedPluginType, PluginType.SOURCE.getType())) {
            return PluginType.SOURCE;
        }
        if (StringUtils.equalsIgnoreCase(normalizedPluginType, PluginType.SINK.getType())) {
            return PluginType.SINK;
        }
        if (StringUtils.equalsIgnoreCase(normalizedPluginType, PluginType.TRANSFORM.getType())) {
            return PluginType.TRANSFORM;
        }
        throw new IllegalArgumentException(
                String.format(
                        "Unsupported plugin type '%s'. Only '%s', '%s' and '%s' are supported.",
                        normalizedPluginType,
                        PluginType.SOURCE.getType(),
                        PluginType.SINK.getType(),
                        PluginType.TRANSFORM.getType()));
    }

    private String normalizePluginName(String pluginName) {
        if (StringUtils.isBlank(pluginName)) {
            throw new IllegalArgumentException(
                    String.format("Parameter '%s' cannot be empty.", PARAM_PLUGIN));
        }
        return pluginName.trim().toLowerCase(Locale.ROOT);
    }

    private OptionRuleResponse.RequiredOptionMetadata toRequiredOptionMetadata(
            RequiredOption requiredOption) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Set type to exactly one of: source, sink, transform (case-insensitive).
  2. Map legacy connector terminology to SeaTunnel types (input->source, output->sink, processor->transform) before calling.
  3. Add client-side validation of the type value against the three accepted tokens.

Example fix

// before
curl 'http://host:8080/option-rules?type=processor'
// after
curl 'http://host:8080/option-rules?type=transform'
Defensive patterns

Strategy: validation

Validate before calling

const VALID = ["source", "sink", "transform"];
if (!VALID.includes((type || "").trim().toLowerCase())) throw new Error("type must be one of " + VALID.join(", "));

Type guard

function isSupportedPluginType(v) {
  return ["source", "sink", "transform"].includes(String(v).trim().toLowerCase());
}

Try / catch

try { fetchOptionRules(type); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unsupported plugin type")) { throw new UserInputError(e.getMessage()); } throw e; }

Prevention

When it happens

Trigger: GET /option-rules?type=foo (misspelled or unsupported value such as 'Processor', 'transformv2', 'input').

Common situations: Confusion with Flink/Spark terminology (input/output/processor) when querying SeaTunnel option rules; typos like 'souce'; camelCase or prefixed names not matching the accepted tokens; copying type values from other SeaTunnel APIs with broader enums.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/ec054a778b83e2c5. Report an issue: GitHub.