kestra-io/kestra · error · PebbleException

Failed to execute HTTP Request, server respond with status {

Error message

Failed to execute HTTP Request, server respond with status {code} : {reason}

What it means

Thrown by the 'http' Pebble function when the remote server returns a response with an error status code. The wrapped HttpClientResponseException carries the full response; the message echoes the status code and reason phrase (e.g. 404 : Not Found).

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/HttpFunction.java:110

        if (args.containsKey("body")) {
            body = toRequestBody(args, self, lineNumber, contentType);
        }

        UriBuilder uriWithQueryBuilder = UriBuilder.of(uri);
        query.forEach(uriWithQueryBuilder::queryParam);

        HttpRequest httpRequest = HttpRequest.of(uriWithQueryBuilder.build(), method, body, headers);
        HttpConfiguration httpConfiguration = Optional.ofNullable(args.get("options"))
            .map(o -> JacksonMapper.toMap(o, HttpConfiguration.class))
            .orElse(null);

        try (HttpClient httpClient = new HttpClient(runContext, httpConfiguration)) {
            HttpResponse<Object> response = httpClient.request(httpRequest, Object.class);
            return response.getBody();
        } catch (HttpClientResponseException e) {
            if (e.getResponse() != null) {
                String msg = "Failed to execute HTTP Request, server respond with status " + e.getResponse().getStatus().getCode() + " : " + e.getResponse().getStatus().getReason();
                throw new PebbleException(e, msg, lineNumber, self.getName());
            } else {
                throw new PebbleException(e, "Failed to execute HTTP request ", lineNumber, self.getName());
            }
        } catch (HttpClientException | IllegalVariableEvaluationException | IOException e) {
            throw new PebbleException(e, "Failed to execute HTTP request ", lineNumber, self.getName());
        }
    }

    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();

View on GitHub (pinned to 823fada927)

Solutions

  1. Read the status code and reason in the message; fix auth/URL/payload accordingly.
  2. For transient 5xx/429, add a retry policy via the 'options' argument (retry/timeouts) or wrap the task in a retry.
  3. Confirm the endpoint contract (method, path, query params, body schema) against the API docs.
  4. Handle expected business-level error codes explicitly instead of letting them fail the flow.

Example fix

// before
{{ http(uri, method='GET') }}
// after — add retry/options for transient failures
{{ http(uri, method='GET', options={'retry': {'maxAttempt': 3}, 'timeout': {'read': 'PT30S'}}) }}
Defensive patterns

Strategy: retry

Try / catch

# Flow-level error handling around the task that uses http()
id: call_api
tasks:
  - id: http
    type: io.kestra.plugin.core.log.Log
    message: "{{ http(uri, options={'retry': {'maxAttempt': 3}}) }}"
errors:
  - id: on_failure
    type: io.kestra.plugin.core.log.Log
    message: "HTTP call failed: {{ execution.error }}"

Prevention

When it happens

Trigger: The remote endpoint returns 4xx/5xx — wrong URL (404), missing/invalid auth (401/403), bad payload (400), server error (500/502/503), or rate limiting (429).

Common situations: Expired API token, wrong base URL, schema drift between expected and actual payload, hitting an endpoint behind auth, or a transient 5xx during a deploy.

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/a6b160c918a91755. Report an issue: GitHub.