kestra-io/kestra · error · PebbleException
Couldn't parse the request body
Error message
Couldn't parse the request body
What it means
Thrown by 'http' while building the request body entity: after the body writer serializes the object into a byte array, constructing the Apache HC ByteArrayEntity with the given contentType raises an IOException. In practice a malformed contentType MIME string is the usual culprit.
Source
Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/HttpFunction.java:136
private Map<String, List<String>> singleValueToListForHeaders(Map<String, Object> m) {
return m.entrySet().stream()
.map(e -> Map.entry(e.getKey(), e.getValue() instanceof String valueStr ? List.of(valueStr) : (List<String>) e.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
private HttpRequest.RequestBody toRequestBody(Map<String, Object> args, PebbleTemplate self, int lineNumber, String contentType) {
HttpRequest.RequestBody body;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Class<T> bodyClass = (Class<T>) args.get("body").getClass();
MessageBodyWriter<T> bodyWriter = defaultMessageBodyHandlerRegistry.findWriter(Argument.of(bodyClass), MediaType.of(contentType)).orElse(FALLBACK_CONTENT_WRITER);
bodyWriter.writeTo(Argument.of(bodyClass), MediaType.of(contentType), (T) args.get("body"), new SimpleHttpHeaders(), byteArrayOutputStream);
try {
body = HttpRequest.RequestBody.from(
new ByteArrayEntity(byteArrayOutputStream.toByteArray(), ContentType.create(contentType))
);
} catch (IOException e) {
throw new PebbleException(e, "Couldn't parse the request body", lineNumber, self.getName());
}
return body;
}
private void throwIfMissingArgs(Map<String, Object> args, PebbleTemplate self, int lineNumber) {
if (!args.containsKey("uri")) {
throw new PebbleException(null, "The 'http' function expects an argument 'uri'.", lineNumber, self.getName());
}
}
@Override
public List<String> getArgumentNames() {
return List.of("uri", "method", "query", "body", "contentType", "headers", "options", "accept");
}
@Override
public Map<String, String> getArgumentDefaults() {
HashMap<String, String> defaults = new HashMap<>();View on GitHub (pinned to 823fada927)
Solutions
- Use a valid MIME type string for contentType, e.g. 'application/json', 'application/yaml', 'text/plain'.
- If contentType is templated, render it separately to confirm it resolves to a real MIME type.
- Omit contentType to accept the 'application/json' default.
Example fix
// before
{{ http(uri, method='POST', body=payload, contentType='json') }}
// after
{{ http(uri, method='POST', body=payload, contentType='application/json') }} Defensive patterns
Strategy: validation
Validate before calling
{% set ct = contentType ?? 'application/json' %}{% if '/' not in ct %}{% set ct = 'application/json' %}{% endif %}{{ http(uri, method='POST', body=payload, contentType=ct) }} Prevention
- Always pass contentType as a full MIME type in type/subtype form.
- Omit contentType unless you need a non-JSON type.
- Render templated contentType values separately to confirm they are real MIME types.
When it happens
Trigger: Passing a malformed contentType such as 'application//json', 'json', or an empty string to http together with a body.
Common situations: Typo or missing slash in the contentType, passing a file extension instead of a MIME type, or a templated contentType that rendered to an unexpected value.
Related errors
- Unsupported content type
- Couldn't write the request body as YAML
- Failed to execute HTTP Request, server respond with status {
- Failed to execute HTTP request
- The 'http' function expects an argument 'uri'.
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/07c51cfac2281c76.
Report an issue: GitHub.