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
- Wrap scalars in JSON: pass `{ value: 42 }` or a JSON string `Json.stringify(x)`.
- Convert Maps/Lists pass-through as-is; for primitives build a JSON string: `response.body(JSON.stringify(42))`.
- For binary data use the byte-array-aware setBody API instead of the JS body() hook.
- 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
- Only pass strings, XML nodes, Maps, or Lists as response bodies
- Stringify primitives and custom objects before assigning
- In mock handlers, normalize the computed body once in a helper
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
- cache() second argument must be a function:
- karate.request is only available in mock context
- multipart fields expects a map:
- multipart files entry must be a map:
- multipart files expects a list or map:
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)