๐ด The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
2026-02-14 09:30:45.200 ERROR 8842 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.devinhyderabad.entity.User]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)] with root cause
java.lang.StackOverflowError: nullโก Quick Fix Works 80% of the time
Add @JsonIgnore to the 'child' side of the relationship to stop Jackson from serializing it.
@ManyToOne
@JoinColumn(name = "department_id")
@JsonIgnore
private Department department;๐ ๏ธ Solutions (3 Ways to Fix)
Use @JsonIgnore on the inverse side
๐ Use this for a quick fix when you don't need the related data in the JSON response.
If User has a List of Orders, and Order has a User field, add @JsonIgnore to the User field in the Order class. Jackson will stop traversing there.
@Entity
public class Order {
@ManyToOne
@JsonIgnore // Stops infinite loop
private User user;
}Use @JsonManagedReference and @JsonBackReference
๐ Use this if you want to keep the data in the JSON but break the cycle cleanly.
Annotate the 'parent' side (the List) with @JsonManagedReference, and the 'child' side (the object reference) with @JsonBackReference. Jackson handles the cycle perfectly.
@Entity
public class User {
@OneToMany(mappedBy = "user")
@JsonManagedReference
private List<Order> orders;
}
@Entity
public class Order {
@ManyToOne
@JsonBackReference
private User user;
}Return DTOs instead of Entities
๐ Use this as the enterprise best practice.
Never return JPA Entities directly from @RestController. Map them to DTOs inside your service layer. This completely avoids JSON recursion and lazy loading exceptions.
@GetMapping
public List<UserDTO> getUsers() {
return userService.getAllUsers().stream()
.map(u -> new UserDTO(u.getName(), u.getOrders().size()))
.collect(Collectors.toList());
}๐ Version Notes
Uses Jackson 2.x. Standard recursion handling.
Uses Jackson 2.15+. Stricter memory limits cause StackOverflow to trigger faster.
๐ง Why this Happens
Tap to expand the deep technical explanation
Your JPA entities have a bidirectional relationship (e.g., User has a List of Orders, and Order has a reference back to User). When Spring tries to convert the User to JSON, Jackson goes to User -> Orders -> User -> Orders indefinitely until the JVM runs out of stack memory.
The HITEC City Parking Spot Analogy:
Imagine two mirrors facing each other. You look into one mirror and see an infinite tunnel of mirrors reflecting each other. Jackson tries to serialize that infinite tunnel and crashes.
๐ก๏ธ How to Prevent This Next Time
Always separate your database entities from your API responses using Data Transfer Objects (DTOs).