Spring Boot Remove Whitelabel Error Page

Learn spring boot remove whitelabel error page with practical examples, diagrams, and best practices. Covers spring, spring-boot development techniques with visual explanations.

Eliminating Spring Boot's Whitelabel Error Page

Hero image for Spring Boot Remove Whitelabel Error Page

Learn how to effectively remove or customize Spring Boot's default Whitelabel Error Page for a more professional user experience.

Spring Boot provides a convenient default error page, often referred to as the "Whitelabel Error Page," which appears for unhandled exceptions or HTTP errors (like 404 Not Found, 500 Internal Server Error). While useful for development, this generic page is rarely suitable for production environments as it can expose internal details and offers a poor user experience. This article will guide you through various strategies to remove or replace this default page with custom error handling.

Understanding the Whitelabel Error Page

The Whitelabel Error Page is part of Spring Boot's auto-configuration. When an error occurs, Spring Boot's ErrorMvcAutoConfiguration kicks in. It registers an ErrorController that maps to /error and renders a default error view. This view is typically a simple HTML page displaying the HTTP status, error message, and sometimes a stack trace. For REST APIs, it returns a JSON response with similar information.

flowchart TD
    A[User Request] --> B{Error Occurs?}
    B -->|No| C[Normal Controller]
    B -->|Yes| D[Spring Boot's Error Handling]
    D --> E{Custom Error Page Configured?}
    E -->|No| F["Whitelabel Error Page (Default)"]
    E -->|Yes| G[Custom Error Page/Handler]
    F --> H[Generic Error Display]
    G --> I[User-Friendly Error Display]

Flow of Spring Boot Error Handling

Method 1: Disabling the Whitelabel Error Page

The simplest way to get rid of the Whitelabel Error Page is to disable its auto-configuration. This is generally not recommended for production as it leaves you without any default error handling, potentially showing a blank page or a container-specific error page. However, it can be useful in specific scenarios where you want full control over every aspect of error handling without Spring Boot's intervention.

spring:
  mvc:
    throw-exception-if-no-handler-found: true
  resources:
    add-mappings: false
server:
  error:
    whitelabel:
      enabled: false

Method 2: Customizing the Error Page with HTML/Thymeleaf

The most common and recommended approach is to provide your own custom error pages. Spring Boot will automatically pick up static HTML files or templated views (like Thymeleaf, FreeMarker, JSP) for specific HTTP status codes if they are placed in the correct directory. For example, a 404.html or 500.html file in src/main/resources/static/error/ or src/main/resources/templates/error/ will be used.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Page Not Found</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
        h1 { color: #dc3545; }
    </style>
</head>
<body>
    <h1>404 - Page Not Found</h1>
    <p>The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.</p>
    <a href="/">Go to Homepage</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Internal Server Error</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
        h1 { color: #dc3545; }
    </style>
</head>
<body>
    <h1>500 - Internal Server Error</h1>
    <p>Oops! Something went wrong on our server. We're working to fix it.</p>
    <p th:if="${trace}">Error details: <pre th:text="${trace}"></pre></p>
    <a href="/">Go to Homepage</a>
</body>
</html>

Method 3: Implementing a Custom ErrorController

For more programmatic control over error handling, you can implement your own ErrorController. This allows you to define custom logic for different error types, log errors, and return specific views or JSON responses. Your custom controller needs to implement Spring Boot's ErrorController interface and override the getErrorPath() method.

package com.example.demo.error;

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;

@Controller
public class CustomErrorController implements ErrorController {

    @RequestMapping("/error")
    public ModelAndView handleError(HttpServletRequest request) {
        Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        ModelAndView modelAndView = new ModelAndView("error"); // Renders error.html or error.jsp

        if (status != null) {
            Integer statusCode = Integer.valueOf(status.toString());

            if(statusCode == HttpStatus.NOT_FOUND.value()) {
                modelAndView.setViewName("error/404"); // Renders src/main/resources/templates/error/404.html
                modelAndView.addObject("errorMessage", "The page you requested was not found.");
                return modelAndView;
            } else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
                modelAndView.setViewName("error/500"); // Renders src/main/resources/templates/error/500.html
                modelAndView.addObject("errorMessage", "An unexpected error occurred.");
                return modelAndView;
            }
        }
        modelAndView.setViewName("error/generic"); // Fallback for other errors
        modelAndView.addObject("errorMessage", "An unknown error occurred.");
        return modelAndView;
    }

    @Override
    public String getErrorPath() {
        return "/error";
    }
}

Method 4: Global Exception Handling with @ControllerAdvice

For RESTful APIs or more fine-grained control over exceptions, @ControllerAdvice combined with @ExceptionHandler is a powerful approach. This allows you to centralize exception handling across multiple controllers and return specific JSON error responses.

package com.example.demo.error;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex) {
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", LocalDateTime.now());
        body.put("status", HttpStatus.NOT_FOUND.value());
        body.put("error", "Not Found");
        body.put("message", "The requested resource was not found.");
        body.put("path", ex.getRequestURL());
        return new ResponseEntity<>(body, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity<Object> handleAllUncaughtException(Exception ex) {
        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", LocalDateTime.now());
        body.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        body.put("error", "Internal Server Error");
        body.put("message", "An unexpected error occurred. Please try again later.");
        // Optionally log the exception details here
        return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

1. Choose Your Strategy

Decide whether you need a simple static error page, a dynamic templated page, a custom ErrorController for more logic, or @ControllerAdvice for API-specific error handling.

2. Implement Your Solution

Based on your chosen strategy, create the necessary HTML files, Thymeleaf templates, or Java classes (e.g., CustomErrorController, GlobalExceptionHandler).

3. Configure application.properties/application.yml

Adjust Spring Boot properties as needed, especially server.error.whitelabel.enabled or spring.mvc.throw-exception-if-no-handler-found for advanced scenarios.

4. Test Thoroughly

Ensure your custom error pages or handlers are correctly displayed for various error scenarios (e.g., 404, 500, custom exceptions) in both development and production environments.