🔴 The Error You're Seeing

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

ERROR LOG2026-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;

🧠 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 Reproduce Confirm this is your error

Return a JPA entity with a bidirectional @OneToMany/@ManyToOne relationship directly from a controller. Jackson serializes both sides forever and throws JsonMappingException: Infinite recursion (StackOverflowError).

🛠️ Solutions (3 Ways to Fix)

Solution 1✓ Most common cause

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; }
Solution 2

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; }
Solution 3

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

Spring Boot 2.x

Uses Jackson 2.x. Standard recursion handling.

Spring Boot 3.x

Uses Jackson 2.15+. Stricter memory limits cause StackOverflow to trigger faster.

🛡️ How to Prevent This Next Time

Always separate your database entities from your API responses using Data Transfer Objects (DTOs).