🔴 The Error You're Seeing

Confirm this matches your console output. If it does, you're in the right place.

ERROR LOGorg.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: "{"error": "Invalid email format"}" at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:68) at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:104)

⚡ Quick Fix Works 80% of the time

Log the exact request body you are sending to the external API and compare it to their documentation.

log.info("Sending payload: {}", requestBody); restTemplate.postForObject(url, requestBody, String.class);

🧠 Why this Happens

Tap to expand the deep technical explanation

Your Spring Boot app used `RestTemplate` or `WebClient` to send a POST/PUT request to an external API. The external server read your payload, found it invalid (missing fields, wrong format), and responded with a 400 Bad Request. Spring translated this into an exception.

The HITEC City Parking Spot Analogy:

It's like mailing a package with the wrong customs declaration form. The border patrol (external API) inspects it, sees the form is invalid, and sends the package back to you (400 Bad Request).

🔁 How to Reproduce Confirm this is your error

Use `RestTemplate` to POST `{"email": "null"}` to an API that strictly requires a valid email string. The API will return 400, and RestTemplate will throw the exception.

🛠️ Solutions (5 Ways to Fix)

Solution 1✓ Most common cause

Log the outgoing request body

👉 Use this to debug exactly what you are sending.

Print the JSON payload right before sending it to verify its structure.

ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(userRequest); log.info("Outgoing JSON: {}", json); restTemplate.postForObject(url, userRequest, String.class);
Solution 2

Intercept the full response body

👉 Use this to see the exact error message from the external server.

The exception contains the response body. Extract it to see why the external API rejected the request.

try { restTemplate.postForObject(url, req, String.class); } catch (HttpClientErrorException e) { String responseBody = e.getResponseBodyAsString(); log.error("External API error: {}", responseBody); }
Solution 3

Fix Content-Type header

👉 Use this if you are sending JSON but the header is set to text/plain.

The external API expects JSON, but your client might be sending the wrong Content-Type header.

HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<UserRequest> entity = new HttpEntity<>(req, headers); restTemplate.postForObject(url, entity, String.class);
Solution 4

Fix serialization issues (e.g., null fields)

👉 Use this if the external API requires fields that your object is sending as null.

Ensure your DTO is populated correctly before sending. Use @JsonInclude to control nulls.

@JsonInclude(JsonInclude.Include.NON_NULL) public class UserRequest { private String email; // Ensure this isn't null }
Solution 5

Use WebClient for better error handling

👉 Use this if you want reactive, declarative error handling.

WebClient's onStatus method is much cleaner for handling 4xx/5xx errors than RestTemplate's try-catch.

webClient.post().uri(url) .bodyValue(req) .retrieve() .onStatus(HttpStatusCode::is4xxClientError, response -> response.bodyToMono(String.class).map(Exception::new)) .bodyToMono(String.class) .block();

📋 Version Notes

Spring Boot 2.x

Throws HttpClientErrorException.

Spring Boot 3.x

Throws HttpClientErrorException, but WebClient is preferred for new apps.

🛡️ How to Prevent This Next Time

Always write integration tests for external API calls using MockWebServer to ensure your payload matches their expected format exactly.