๐ด The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
org.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)
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);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);
}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);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
}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
Throws HttpClientErrorException.
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.