karatelabs/karate · error · RuntimeException

params() needs a map argument

Error message

params() needs a map argument

What it means

karate's params() JS helper on HttpRequestBuilder only accepts a single Map argument (matching the `param` keyword semantics: scalar or list values per key). The library throws this RuntimeException when params() is called with no arguments or with a non-Map first argument, because there is no meaningful interpretation of other inputs.

Solutions

  1. Pass a single map argument: `params({ page: 1, tag: ['x','y'] })`.
  2. If you have key/value pairs, build a map first: `params({ [k]: v })` or collect into an object.
  3. Use `param(name, value)` for one-off additions instead of params().
  4. Wrap dynamic inputs with a check: `if (q && typeof q === 'object' && !Array.isArray(q)) params(q)`.­

Example fix

// before
params('page=1&size=10')
// after
params({ page: 1, size: 10 })
Defensive patterns

Strategy: validation

Validate before calling

function safeParams(builder, m) { if (m && typeof m === 'object' && !Array.isArray(m)) builder.params(m); return builder; }

Type guard

function isPlainMap(v) { return v != null && typeof v === 'object' && !Array.isArray(v); }

Try / catch

try { builder.params(q); } catch (e) { if (('' + e).includes('needs a map argument')) builder.param('raw', String(q)); else throw e; }

Prevention

When it happens

Trigger: Calling `params()` with zero arguments, or `params('a=1')`, `params([['a','b']])`, or any string/list/scalar instead of a JS object like `params({a: '1'})`.

Common situations: Porting from older Karate DSL where params took key/value pairs; passing a URL-encoded query string instead of a map; forgetting the argument entirely in a JS `configure` or request block.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/b9cfba8b3778b5f8. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/http/HttpRequestBuilder.java:746

        return args -> {
            if (args.length < 2) {
                throw new RuntimeException("param() needs two arguments");
            }
            param(args[0] + "", args[1] + "");
            return this;
        };
    }

    /**
     * The JS-facing plural forms of {@link #param} and {@link #header}. The Java
     * {@link #params(Map)} takes a {@code Map<String, List<String>>} and replaces what was
     * there, which is awkward to satisfy from JS - these accumulate and accept a scalar or a
     * list per key, matching the {@code params} and {@code headers} keywords.
     */
    private JavaInvokable params() {
        return args -> {
            if (args.length == 0 || !(args[0] instanceof Map<?, ?> map)) {
                throw new RuntimeException("params() needs a map argument");
            }
            map.forEach((k, v) -> {
                if (v instanceof List<?> list) {
                    for (Object item : list) {
                        if (item != null) {
                            param(k + "", item + "");
                        }
                    }
                } else if (v != null) {
                    param(k + "", v + "");
                }
            });
            return this;
        };
    }

    @SuppressWarnings("unchecked")
    private JavaInvokable headers() {

View on GitHub (pinned to a22eb90246)