apache/seatunnel · error · IllegalArgumentException

Invalid Params format in Params.

Error message

Invalid Params format in Params.

What it means

Thrown by RestUtil.buildRequestParams when parsing the REST URI query string. Each parameter is split on '=' and both key and value are indexed; a parameter without a value (e.g. 'flag' or 'a==b') causes an IndexOutOfBoundsException, which is rethrown as this IllegalArgumentException. It signals a malformed query string sent to the SeaTunnel REST API.

Solutions

  1. Inspect the request URL and fix the query string so every parameter has the form key=value
  2. Ensure no empty segments exist (no '&&', no trailing '&', no bare keys)
  3. URL-encode values that contain '=' or '&' so splitting is not disrupted
  4. Log the full request URI server-side to identify the offending parameter

Example fix

// before
curl 'http://host:5801/job-info?jobId'
// after
curl 'http://host:5801/job-info?jobId=12345'
Defensive patterns

Strategy: validation

Validate before calling

function validateQuery(qs) {
  if (!qs) return true;
  return qs.replace(/^[?]/, '').split('&').every(p => p.length > 0 && p.includes('='));
}
if (!validateQuery(queryString)) throw new Error('Malformed query string: each param must be key=value');

Try / catch

try {
  restUtil.buildRequestParams(uri);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Invalid Params format")) {
    log.error("Malformed query string: " + uri);
    // fix request URL and retry
  } else throw e;
}

Prevention

When it happens

Trigger: Calling any SeaTunnel REST endpoint with a malformed query string: a parameter missing its '=' and value (e.g. '?jobId'), an empty parameter between ampersands (e.g. '?a=1&&b=2'), or a trailing '&' with nothing after it.

Common situations: Hand-built curl/browser URLs with typos, scripting that appends '&' or partial parameters programmatically, URL templates where a variable failed to interpolate (leaving 'jobId=' empty or 'jobId' alone), or proxies rewriting query strings.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/utils/RestUtil.java:64

    public static JsonNode convertByteToJsonNode(byte[] byteData) throws IOException {
        return objectMapper.readTree(byteData);
    }

    public static void buildRequestParams(Map<String, String> requestParams, String uri) {
        requestParams.put(RestConstant.JOB_ID, null);
        requestParams.put(RestConstant.IS_START_WITH_SAVE_POINT, String.valueOf(false));
        uri = StringUtil.stripTrailingSlash(uri);
        if (!uri.contains("?")) {
            return;
        }
        int indexEnd = uri.indexOf('?');
        try {
            for (String s : uri.substring(indexEnd + 1).split("&")) {
                String[] param = s.split("=");
                requestParams.put(param[0], URLDecoder.decode(param[1], "UTF-8"));
            }
        } catch (IndexOutOfBoundsException e) {
            throw new IllegalArgumentException("Invalid Params format in Params.");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException("Unsupported encoding exists in the parameter.");
        }
        if (Boolean.parseBoolean(requestParams.get(RestConstant.IS_START_WITH_SAVE_POINT))
                && requestParams.get(RestConstant.JOB_ID) == null) {
            throw new IllegalArgumentException("Please provide jobId when start with save point.");
        }
    }

    public static Config buildConfig(JsonNode jsonNode) {
        Map<String, Object> objectMap = JsonUtils.toMap(jsonNode);
        return ConfigBuilder.of(objectMap);
    }

    public static List<Tuple2<Map<String, String>, Config>> buildConfigList(JsonNode jsonNode) {
        return StreamSupport.stream(jsonNode.spliterator(), false)
                .filter(JsonNode::isObject)
                .map(

View on GitHub (pinned to cf67b549a7)