How to Debug and Resolve 400 Errors in Spring MVC

This article explains how Spring MVC processes HTTP 400 errors, walks through the DispatchServlet and exception‑handling flow, shows key code snippets, and provides practical ways to implement global or custom exception resolvers to handle common 400‑causing exceptions.

Programmer DD
Programmer DD
Programmer DD
How to Debug and Resolve 400 Errors in Spring MVC

Developers often encounter HTTP 400 or 500 errors in Spring MVC applications before the request reaches a controller, leaving them uncertain about the cause.

Spring MVC starts processing a request in DispatchServlet.doDispatch(). By debugging this method you can see the exception stack and then follow the flow to processDispatchResult().

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // ... (code omitted)
    try {
        ModelAndView mv = null;
        Exception dispatchException = null;
        try {
            // ... invoke the handler
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
        } finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                return;
            }
        }
        applyDefaultViewName(request, mv);
        mappedHandler.applyPostHandle(processedRequest, response, mv);
    } catch (Exception ex) {
        dispatchException = ex; // e.g., TypeMismatchException
    }
    processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

The processDispatchResult() method checks the exception type. If it is not a ModelAndViewDefiningException, it delegates to processHandlerException().

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
        HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
    boolean errorView = false;
    if (exception != null) {
        if (exception instanceof ModelAndViewDefiningException) {
            logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException) exception).getModelAndView();
        } else {
            Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
            mv = processHandlerException(request, response, handler, exception);
            errorView = (mv != null);
        }
    }
    // ... (other code omitted)
}

Spring MVC maintains a list of HandlerExceptionResolver implementations such as ExceptionHandlerExceptionResolver, ResponseStatusExceptionResolver, DefaultHandlerExceptionResolver, and any custom resolvers. It iterates over this list to find one that can handle the exception.

The abstract base class AbstractHandlerExceptionResolver implements HandlerExceptionResolver and defines the template method resolveException():

public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
        Object handler, Exception ex) {
    if (shouldApplyTo(request, handler)) {
        logException(ex, request);
        prepareResponse(ex, response);
        return doResolveException(request, response, handler, ex);
    } else {
        return null;
    }
}

The concrete doResolveException() method checks the exception type and calls the corresponding handleXXX() method, many of which send a 400 response, e.g.:

protected ModelAndView handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
        HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
    response.sendError(400, ex.getMessage());
    return new ModelAndView();
}
// similar handlers for ServletRequestBindingException, TypeMismatchException, HttpMessageNotReadableException, etc.

To solve 400 errors, you can define a global @ControllerAdvice with @ExceptionHandler methods or implement a custom HandlerExceptionResolver:

public class ApiHandlerExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception exception) {
        ModelAndView model = new ModelAndView();
        // custom handling logic
        return model;
    }
}

By properly handling exceptions that commonly produce 400 responses, such as TypeMismatchException or BindException, you can return clear error information and avoid confusion.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backendexception-handling400-errorspring-mvc
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.