Skip to content

Fix: Spring Boot Whitelabel Error Page - This application has no explicit mapping

FixDevs ·

Quick Answer

How to fix the Spring Boot Whitelabel Error Page caused by missing controller mappings, wrong component scan, wrong package structure, and missing Thymeleaf templates.

The Error

You open your Spring Boot app in the browser and see:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

There was an unexpected error (type=Not Found, status=404).

Or variations:

There was an unexpected error (type=Internal Server Error, status=500).
There was an unexpected error (type=Method Not Allowed, status=405).

Spring Boot could not find a controller method to handle the requested URL. Instead of a raw HTTP error, it shows the Whitelabel Error Page as a fallback.

Why This Happens

Spring Boot maps HTTP requests to @Controller or @RestController methods using @RequestMapping, @GetMapping, @PostMapping, etc. When no mapping matches the requested URL, Spring returns a 404 and shows the whitelabel page.

Common causes:

  • Missing or wrong @RequestMapping. The URL you are accessing does not match any controller endpoint.
  • Controller not scanned. The controller class is not in a package that Spring Boot scans.
  • Wrong HTTP method. You send a GET request but the controller only handles POST.
  • Missing @RestController or @Controller. The class is not annotated as a controller.
  • Application class in the wrong package. The @SpringBootApplication class must be in a root package that encompasses all controllers.
  • Thymeleaf template not found. A @Controller method returns a view name but the template does not exist.

Fix 1: Add a Controller with the Right Mapping

The most common fix. Create a controller that handles the URL you are accessing:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "Hello, World!";
    }

    @GetMapping("/api/status")
    public Map<String, String> status() {
        return Map.of("status", "running");
    }
}

Key annotations:

  • @RestController — for REST APIs (returns JSON/text directly)
  • @Controller — for server-rendered views (returns template names)
  • @GetMapping("/path") — handles GET requests to /path
  • @PostMapping("/path") — handles POST requests to /path

Check that the URL matches:

@GetMapping("/api/users")  // Accessible at http://localhost:8080/api/users
public List<User> getUsers() { ... }

If you access http://localhost:8080/users (missing /api), you get the whitelabel page.

Fix 2: Fix the Package Structure

Spring Boot’s @SpringBootApplication enables component scanning starting from the package the main class is in. If your controllers are in a package outside this scan range, they are invisible to Spring.

Broken structure:

com.example.app.MyApplication.java       ← @SpringBootApplication
com.other.controllers.UserController.java  ← NOT scanned!

Fixed — controllers in a sub-package:

com.example.app.MyApplication.java
com.example.app.controller.UserController.java  ← Scanned ✓
com.example.app.service.UserService.java         ← Scanned ✓

The @SpringBootApplication class at com.example.app scans com.example.app and all sub-packages.

Fix — explicitly specify scan packages:

@SpringBootApplication(scanBasePackages = {"com.example.app", "com.other.controllers"})
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Pro Tip: Always put your @SpringBootApplication class in the root package of your project. Every controller, service, and repository should be in a sub-package. This is the standard convention and avoids scanning issues.

Fix 3: Check @Controller vs @RestController

Using @Controller without Thymeleaf or a view resolver causes a different problem — Spring looks for a template file instead of returning the string:

Broken:

@Controller
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "Hello, World!";  // Spring looks for a template named "Hello, World!"
    }
}

Fixed — use @RestController for API responses:

@RestController
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "Hello, World!";  // Returns the string directly
    }
}

Or use @ResponseBody with @Controller:

@Controller
public class HomeController {

    @GetMapping("/")
    @ResponseBody
    public String home() {
        return "Hello, World!";
    }
}

For template-based responses, create the template:

If you want @Controller to render HTML templates, add Thymeleaf and create the template:

@Controller
public class HomeController {

    @GetMapping("/")
    public String home(Model model) {
        model.addAttribute("message", "Hello!");
        return "home";  // Looks for src/main/resources/templates/home.html
    }
}

Create src/main/resources/templates/home.html:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
    <h1 th:text="${message}">Placeholder</h1>
</body>
</html>

Fix 4: Fix the HTTP Method

A 405 whitelabel error means the URL exists but not for the HTTP method you used:

@PostMapping("/api/users")
public User createUser(@RequestBody User user) { ... }

Accessing GET http://localhost:8080/api/users in the browser returns 405 because only POST is mapped.

Fix: Add the correct mapping:

@GetMapping("/api/users")
public List<User> getUsers() { ... }

@PostMapping("/api/users")
public User createUser(@RequestBody User user) { ... }

Or use @RequestMapping for multiple methods:

@RequestMapping(value = "/api/users", method = {RequestMethod.GET, RequestMethod.POST})
public ResponseEntity<?> handleUsers(HttpServletRequest request) { ... }

Fix 5: Check Server Port and Context Path

You might be accessing the wrong URL:

Check the port:

# application.properties
server.port=8081

If the port is 8081, access http://localhost:8081/, not http://localhost:8080/.

Check the context path:

# application.properties
server.servlet.context-path=/api/v1

With this setting, all URLs are prefixed: http://localhost:8080/api/v1/users instead of http://localhost:8080/users.

Check for a reverse proxy prefix:

Behind Nginx or a load balancer, the path might be different. Check your proxy configuration.

Fix 6: Debug Registered Mappings

See exactly which URLs Spring Boot has registered:

Enable Actuator:

Add to pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

In application.properties:

management.endpoints.web.exposure.include=mappings

Access http://localhost:8080/actuator/mappings to see all registered URL mappings.

Or add debug logging:

logging.level.org.springframework.web=DEBUG

Spring logs every registered mapping at startup:

Mapped "{[/api/users],methods=[GET]}" onto public java.util.List<User> UserController.getUsers()

If your controller is not listed, it is not being scanned (see Fix 2).

Common Mistake: Adding a controller class but forgetting to annotate it with @RestController or @Controller. Without the annotation, Spring does not register it as a request handler. Check that the annotation is present and imported from org.springframework.web.bind.annotation.

Fix 7: Customize the Error Page

If you want to replace the whitelabel page with a custom error page:

Disable the whitelabel page:

server.error.whitelabel.enabled=false

Add a custom error controller:

@Controller
public class CustomErrorController implements ErrorController {

    @RequestMapping("/error")
    public String handleError(HttpServletRequest request) {
        Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

        if (status != null) {
            int statusCode = Integer.parseInt(status.toString());
            if (statusCode == 404) {
                return "error-404";
            }
        }
        return "error";
    }
}

Add static error pages:

Place HTML files in src/main/resources/static/error/:

  • 404.html — displayed for 404 errors
  • 500.html — displayed for 500 errors
  • 4xx.html — catch-all for 4xx errors
  • 5xx.html — catch-all for 5xx errors

Spring Boot automatically serves these based on the error status code.

Fix 8: Fix Spring Security Blocking

Spring Security might block access to your controller before it is even reached:

There was an unexpected error (type=Forbidden, status=403).

Fix: Configure security to permit your endpoints:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/api/public/**").permitAll()
                .anyRequest().authenticated()
            );
        return http.build();
    }
}

For development, permit all (not for production):

http.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());

If authentication itself fails, the issue might be similar to Fix: AWS AccessDeniedException where permissions need to be correctly configured.

Still Not Working?

If the whitelabel error persists:

Check for classpath issues. Run mvn dependency:tree or gradle dependencies to verify all Spring Boot dependencies are present. A missing spring-boot-starter-web dependency means no embedded server.

Check for port conflicts. If port 8080 is already in use, Spring Boot might fail to start or start on a different port. See Fix: Port 3000 already in use for resolving port conflicts.

Check for profile-specific configuration. A different application-{profile}.properties might override your settings:

java -jar app.jar --spring.profiles.active=prod

Check the build output. If using Maven, ensure the project builds without errors:

mvn clean package

For Maven dependency resolution failures, see Fix: Maven could not resolve dependencies.

Check for circular dependencies. Spring might fail to create beans if there are circular dependencies. The error message in the console will mention BeanCurrentlyInCreationException.

Enable full stack trace logging:

server.error.include-stacktrace=always
server.error.include-message=always

This shows the full error details on the whitelabel page, making debugging easier.

If the Gradle build itself fails before you can run the application, see Fix: Gradle build failed.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles