{"record":{"id":"a6b160c918a91755","repo":"kestra-io/kestra","slug":"failed-to-execute-http-request-server-respond-wit","errorCode":null,"errorMessage":"Failed to execute HTTP Request, server respond with status {code} : {reason}","messagePattern":"Failed to execute HTTP Request, server respond with status (.+?) : (.+?)","errorType":"exception","errorClass":"PebbleException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/pebble/functions/HttpFunction.java","lineNumber":110,"sourceCode":"        if (args.containsKey(\"body\")) {\n            body = toRequestBody(args, self, lineNumber, contentType);\n        }\n\n        UriBuilder uriWithQueryBuilder = UriBuilder.of(uri);\n        query.forEach(uriWithQueryBuilder::queryParam);\n\n        HttpRequest httpRequest = HttpRequest.of(uriWithQueryBuilder.build(), method, body, headers);\n        HttpConfiguration httpConfiguration = Optional.ofNullable(args.get(\"options\"))\n            .map(o -> JacksonMapper.toMap(o, HttpConfiguration.class))\n            .orElse(null);\n\n        try (HttpClient httpClient = new HttpClient(runContext, httpConfiguration)) {\n            HttpResponse<Object> response = httpClient.request(httpRequest, Object.class);\n            return response.getBody();\n        } catch (HttpClientResponseException e) {\n            if (e.getResponse() != null) {\n                String msg = \"Failed to execute HTTP Request, server respond with status \" + e.getResponse().getStatus().getCode() + \" : \" + e.getResponse().getStatus().getReason();\n                throw new PebbleException(e, msg, lineNumber, self.getName());\n            } else {\n                throw new PebbleException(e, \"Failed to execute HTTP request \", lineNumber, self.getName());\n            }\n        } catch (HttpClientException | IllegalVariableEvaluationException | IOException e) {\n            throw new PebbleException(e, \"Failed to execute HTTP request \", lineNumber, self.getName());\n        }\n    }\n\n    private Map<String, List<String>> singleValueToListForHeaders(Map<String, Object> m) {\n        return m.entrySet().stream()\n            .map(e -> Map.entry(e.getKey(), e.getValue() instanceof String valueStr ? List.of(valueStr) : (List<String>) e.getValue()))\n            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));\n    }\n\n    private HttpRequest.RequestBody toRequestBody(Map<String, Object> args, PebbleTemplate self, int lineNumber, String contentType) {\n        HttpRequest.RequestBody body;\n        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();\n        Class<T> bodyClass = (Class<T>) args.get(\"body\").getClass();","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/pebble/functions/HttpFunction.java#L92-L128","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","solutions":["Read the status code and reason in the message; fix auth/URL/payload accordingly.","For transient 5xx/429, add a retry policy via the 'options' argument (retry/timeouts) or wrap the task in a retry.","Confirm the endpoint contract (method, path, query params, body schema) against the API docs.","Handle expected business-level error codes explicitly instead of letting them fail the flow."],"exampleFix":"// before\n{{ http(uri, method='GET') }}\n// after — add retry/options for transient failures\n{{ http(uri, method='GET', options={'retry': {'maxAttempt': 3}, 'timeout': {'read': 'PT30S'}}) }}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"# Flow-level error handling around the task that uses http()\nid: call_api\ntasks:\n  - id: http\n    type: io.kestra.plugin.core.log.Log\n    message: \"{{ http(uri, options={'retry': {'maxAttempt': 3}}) }}\"\nerrors:\n  - id: on_failure\n    type: io.kestra.plugin.core.log.Log\n    message: \"HTTP call failed: {{ execution.error }}\"","preventionTips":["Add retry/timeout config under the 'options' argument for flaky remote APIs.","Validate auth credentials and the endpoint contract before relying on the call.","Prefer dedicated HTTP task types (e.g. io.kestra.plugin.core.http.Request) with built-in response handling for non-trivial integrations."],"tags":["pebble","http","network","status-code","remote-api"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}