karatelabs/karate · error · RuntimeException

unsupported response body type:

Error message

unsupported response body type: 

What it means

When building a mock/HTTP response via response.body(value) (applyJsBody), the library converts strings to TEXT, XML Nodes to XML, and Maps/Lists to JSON. Any other JS value type has no defined serialization, so the library throws listing the offending value.

Solutions

  1. Wrap scalars in JSON: pass `{ value: 42 }` or a JSON string `Json.stringify(x)`.
  2. Convert Maps/Lists pass-through as-is; for primitives build a JSON string: `response.body(JSON.stringify(42))`.
  3. For binary data use the byte-array-aware setBody API instead of the JS body() hook.
  4. Type-check in the mock script before assigning the body.­

Example fix

// before
response.body(42) // unsupported
// after
response.body(JSON.stringify({ value: 42 }))
Defensive patterns

Strategy: type-guard

Validate before calling

function toResponseBody(v) { if (v == null) return null; if (typeof v === 'string' || v instanceof Map || Array.isArray(v)) return v; return JSON.stringify(v); }

Type guard

function isSupportedBodyType(v) { return typeof v === 'string' || typeof v === 'object' && v !== null; }

Try / catch

try { response.body(v); } catch (e) { if (('' + e).startsWith('unsupported response body type')) response.body(JSON.stringify({ value: v })); else throw e; }

Prevention

When it happens

Trigger: Passing a number, boolean, JS function, Java object, byte array, or undefined as the response body value from a mock response script.

Common situations: Returning a computed numeric/boolean value from a mock handler; forgetting to JSON.stringify or convert a custom object; variable shadowing leaving a function as the body.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/http/HttpResponse.java:529

     * static factories ({@link #json(Object)}, {@link #text(String)}, etc.).
     */
    public void setBodyDynamic(Object value) {
        applyJsBody(this, value);
    }

    private static void applyJsBody(HttpResponse r, Object value) {
        if (value == null) {
            r.setBody((byte[]) null, null);
        } else if (value instanceof byte[] bytes) {
            r.setBody(bytes, null);
        } else if (value instanceof String s) {
            r.setBody(s, ResourceType.TEXT);
        } else if (value instanceof Node xml) {
            r.setBody(Xml.toString(xml), ResourceType.XML);
        } else if (value instanceof Map<?, ?> || value instanceof List<?>) {
            r.setBody(FileUtils.toBytes(JSONValue.toJSONString(value)), ResourceType.JSON);
        } else {
            throw new RuntimeException("unsupported response body type: " + value);
        }
    }

    // ========== Static factories ==========
    // Build a response in one call. Status + body + Content-Type set atomically
    // — no order trap, no hidden setBody overloads.

    /** {@code 200 OK} with no body. */
    public static HttpResponse ok() {
        HttpResponse r = new HttpResponse();
        r.setStatus(200);
        return r;
    }

    /**
     * {@code 200 OK} with body type inferred (matches the JS-mock dispatch):
     * {@code String→text/plain}, {@code Map/List→application/json},
     * {@code Node→application/xml}, {@code byte[]→no Content-Type}.

View on GitHub (pinned to a22eb90246)