If CSS, JavaScript, images, or an HTML page return 404 in Spring Boot, first identify whether the app uses Servlet MVC or WebFlux, confirm the file is present on the runtime classpath, and compare the requested URL with the active resource mapping. The right fix depends on the Spring Boot version, web stack, packaging, and any custom resource configuration.
Start with the request and the application stack
Record the exact URL that fails, its response status, and whether the failure occurs locally, in a packaged deployment, or both. Then establish whether the application is Servlet-based Spring MVC or reactive WebFlux: their path-pattern property names and customization APIs differ.
- For MVC, the path-pattern property is
spring.mvc.static-path-pattern. - For WebFlux, use
spring.webflux.static-path-pattern; custom resource handlers useWebFluxConfigurer.
Do not change an MVC property in a WebFlux application, or vice versa. In current Spring Boot references, both stacks use spring.web.resources.static-locations for resource locations. See the Spring Boot Servlet web reference and Spring Boot reactive web reference.
Confirm the file is in an active runtime location
For Servlet MVC, the conventional starting point is src/main/resources/static/. Spring Boot also serves classpath resources from public, resources, and META-INF/resources by default, through Spring MVC’s ResourceHttpRequestHandler.
Recommended Free Tools
#1 Best Overall
src/main/resources/
└── static/
├── css/site.css
└── images/logo.svg
With the default root context and mapping, request /css/site.css and /images/logo.svg. The source directory itself is not the runtime lookup: the resource must be copied into the built artifact or otherwise be available at a configured location. If it works in the IDE but not after deployment, inspect the packaged JAR or WAR and verify the resource is present where the running application can load it.
Do not rely on src/main/webapp for a JAR deployment. The Spring Boot Reference Guide says this directory works only with WAR packaging and is silently ignored by most build tools when generating a JAR. See the Spring Boot packaging and static-resource guidance.
Rank #2
Match the browser URL to the resource mapping
Spring Boot’s default static mapping is /**. The request path after the mapping prefix is resolved against the configured resource locations. If you set spring.mvc.static-path-pattern=/resources/**, the example file static/css/site.css is requested as /resources/css/site.css, not /css/site.css. For WebFlux, the corresponding property is spring.webflux.static-path-pattern.
Also account for the servlet context path and any reverse-proxy prefix. The path shown in browser developer tools is the path the deployed app receives only if the proxy and context configuration preserve it as expected. Compare the final request path with the configured pattern and the file’s relative path beneath its resource location.
Rank #3
Check whether configuration replaced the defaults
spring.web.resources.static-locations replaces the default locations; it does not merely add another directory. A custom value can make files in src/main/resources/static disappear from resolution unless that location is included. Verify every configured location’s syntax and that it exists and is available to the deployed process. Spring Boot automatically adds the servlet context root / as a location.
Inspect application properties or YAML, profiles, environment variables, and custom configuration for spring.web.resources.add-mappings or MVC configuration that changes the default handler setup. In the Boot 3.3 reference, an enabled default mapping covers /**; a missing resource can produce NoResourceFoundException, while narrowed or disabled mappings can result in NoHandlerFoundException. These exception details are version-sensitive, so use the reference for the Boot version actually deployed. See the Spring Boot 3.3 Servlet reference.
Rank #4
Review custom resource handlers
A custom WebMvcConfigurer#addResourceHandlers can map a URL prefix to explicit locations. Read the handler mapping and locations together; a correct directory with the wrong URL pattern still produces a failed request.
@Configuration
class WebConfiguration implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public", "classpath:/static/");
}
}
For this example, a request under /resources/ is resolved relative to the configured locations. Use a clear prefix and locations that match the deployed layout. For reactive apps, configure custom handlers using WebFluxConfigurer rather than MVC’s registry. The Spring Framework static-resource reference documents MVC handler configuration.
Free tools Windows power users keep installed
One-click scans. No signup required.
Test the welcome page independently
A static index.html in an active static location can serve as Spring Boot’s welcome page; Boot also looks for an index template. This is fallback behavior, not a mechanism for overriding an application route. If a controller or router already handles /, that handler may win. Check both that the welcome resource is present and that no application route takes precedence. See the Servlet reference and reactive reference.
Use symptom-specific checks for libraries and generated URLs
WebJars
Packaged WebJars are served under /webjars/** by default. Version-agnostic URLs require a WebJars locator library, and the dependency name varies by documented version: the Boot 3.3 reference names webjars-locator-core, while Spring Framework guidance describes webjars-locator-lite. Check the documentation matching the versions in your application rather than copying a dependency name across versions.
Versioned or cached resources
If an asset loads but appears stale, or a generated versioned URL does not match the request, investigate resource versioning and cache configuration rather than treating it as a basic classpath 404. Spring Framework supports version resolvers and cache controls. When combining encoded and version resolvers, register the encoded resolver first, then the version resolver. See the Spring Framework resource handling reference.
Template-generated URLs
Distinguish a raw resource URL that returns 404 from a template that generates the wrong URL. The Boot 3.3 reference documents auto-configured ResourceUrlEncodingFilter support for Thymeleaf and FreeMarker; JSP requires manual filter declaration for rewritten resource URLs. Inspect the rendered HTML and request URL to determine which problem you have.
Choose the smallest fix that matches the deployment
| Situation | Check or adjustment |
|---|---|
| Standard MVC application | Put files under a default classpath location such as src/main/resources/static and use the default /** mapping. |
| Custom URL prefix needed | Configure the matching MVC or WebFlux path pattern, or an explicit resource handler, and request the file beneath that prefix. |
| Custom resource directory | Set the active resource locations explicitly and confirm the default location is included if its files are still needed. |
| JAR deployment | Package assets on the classpath; do not rely on src/main/webapp. |
| WAR deployment | src/main/webapp can be used, but verify the built WAR and deployment context. |
| WebFlux application | Use WebFlux-specific path configuration and customization, not MVC-only settings or APIs. |
For the quickest diagnosis, trace one failing asset from its browser URL, through the active mapping and location, to the file in the deployed artifact. That identifies whether the mismatch is in the URL, configuration, web stack, or packaging.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

