Fix: Spring Boot Web server failed to start. Port 8080 was already in use
Quick Answer
How to fix the Spring Boot error 'Web server failed to start. Port 8080 was already in use' by killing blocking processes, changing ports, fixing IDE issues, and resolving Docker conflicts.
The Error
You start your Spring Boot application and it immediately crashes with:
***************************
APPLICATION FAILED TO START
***************************
Description:
Web server failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.Or the Tomcat variant:
java.net.BindException: Address already in useorg.apache.catalina.LifecycleException: Protocol handler start failed
Caused by: java.net.BindException: Address already in use: bindThe message is straightforward: another process already occupies port 8080, and the embedded server (Tomcat, Jetty, or Undertow) cannot bind to it. Only one process can listen on a given port at a time.
Why This Happens
Spring Boot’s embedded web server tries to bind to port 8080 by default when the application starts. If anything else is already listening on that port, the JVM throws a BindException and Spring translates it into the “port already in use” startup failure.
Common causes:
- A previous instance of your application is still running. You hit “Run” again in your IDE without stopping the first one, or a background
java -jarprocess is still alive. - Another service uses port 8080. Apache Tomcat (standalone), Jenkins, Nexus, WildFly, and many other tools default to 8080.
- A Docker container has port 8080 mapped. Even if the container runs a completely different service, the host-side port binding blocks your Spring app. If you run into Docker port issues frequently, check out the full guide on Docker port conflicts.
- Your IDE did not terminate the previous run cleanly. IntelliJ IDEA and Eclipse sometimes leave zombie Java processes behind, especially after a crash or force-stop.
- A system service or daemon occupies the port. On some Linux distributions, system services like
httpdor custom daemons bind to 8080.
Fix 1: Find and Kill the Process Using Port 8080
The fastest solution is to find whatever is holding port 8080 and kill it.
Linux and macOS
Find the process:
lsof -i :8080You get output like:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 12345 devuser 48u IPv6 0x1234 0t0 TCP *:http-alt (LISTEN)Kill it by PID:
kill 12345If it does not stop, force-kill it:
kill -9 12345One-liner to find and kill in a single command:
lsof -ti :8080 | xargs kill -9You can also use fuser on Linux:
fuser -k 8080/tcpWindows
Find the process:
netstat -ano | findstr :8080Sample output:
TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 12345The last column is the PID. Kill it:
taskkill /PID 12345 /FOr use PowerShell for a cleaner approach:
Get-NetTCPConnection -LocalPort 8080 | Select-Object OwningProcess
Stop-Process -Id 12345 -ForceAfter killing the process, restart your Spring Boot application. The port should now be free.
This approach is nearly identical to how you would fix a port 3000 conflict in Node.js — the underlying OS-level concept is the same regardless of the framework.
Fix 2: Change the Application Port
If you cannot free port 8080 (or simply prefer a different port), tell Spring Boot to use another one.
Using application.properties
Open src/main/resources/application.properties and add:
server.port=8081Using application.yml
If you use YAML configuration:
server:
port: 8081Using a Command-Line Argument
Override the port at startup without changing any files:
java -jar myapp.jar --server.port=8081Using an Environment Variable
Set the port through the SERVER_PORT environment variable:
SERVER_PORT=8081 java -jar myapp.jarOn Windows:
set SERVER_PORT=8081
java -jar myapp.jarPick any port between 1024 and 65535 that is not already in use. Ports below 1024 are privileged and require root/admin access on most systems.
Pro Tip: Use a port number that is easy to remember and unlikely to conflict. Many teams adopt a convention like
8081for service A,8082for service B, etc. Document your port assignments in a shared wiki or README so the entire team stays consistent.
Fix 3: Use a Random Port (Port 0) for Testing
If you are running integration tests or do not care which port the application uses, set the port to 0. Spring Boot will pick a random available port:
server.port=0This is especially useful in @SpringBootTest:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class MyApplicationTests {
@LocalServerPort
private int port;
@Test
void contextLoads() {
// port is the randomly assigned port
System.out.println("Running on port: " + port);
}
}Using RANDOM_PORT eliminates port conflicts entirely during test runs, which matters on CI/CD servers where multiple builds may execute in parallel.
Fix 4: Fix Duplicate Spring Boot Instances
Sometimes you accidentally launch multiple instances of the same application. This is the most common cause of the error when you are certain nothing else should be on port 8080.
Check for Running Java Processes
On Linux/macOS:
ps aux | grep javaOn Windows:
tasklist | findstr javaYou may see two or more java processes running your application. Kill the old ones and keep only the one you intend to use.
Gradle and Maven Daemon Issues
If you use ./gradlew bootRun or mvn spring-boot:run, the build tool may keep a daemon process alive even after you press Ctrl+C.
Stop Gradle daemons:
./gradlew --stopCheck for leftover Maven processes manually and kill them using the methods in Fix 1.
Spring Boot DevTools Hot Reload
If you use spring-boot-devtools, the application restarts automatically on code changes. In rare cases, the old process does not terminate before the new one starts, causing a brief port conflict. Adding a small shutdown delay can help:
spring.devtools.restart.poll-interval=2000
spring.devtools.restart.quiet-period=1000If DevTools restarts consistently fail, check your application’s shutdown hooks and bean destruction order. Misconfigured beans that hang during shutdown can prevent timely port release. This overlaps with Spring bean creation issues — a bean that fails to destroy properly can block a clean restart.
Fix 5: Fix Embedded Server Configuration
Spring Boot auto-configures an embedded Tomcat, Jetty, or Undertow server. Misconfiguration can cause port binding failures beyond a simple conflict.
Multiple Connector Definitions
If you define custom ServerConnector or Connector beans, you might accidentally create a second listener on port 8080:
@Bean
public ServletWebServerFactory serverFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.setPort(8080); // This might conflict with server.port
return factory;
}The server.port property and a programmatic setPort() call can clash. Remove the programmatic setting and rely on server.port alone, or remove the property and control the port entirely in code.
Actuator on the Same Port
Spring Boot Actuator endpoints run on the same port as the main application by default. If you configure management.server.port to a value that conflicts with another process, you get the same bind error — but for the management server:
management.server.port=8081Make sure management.server.port does not collide with server.port or any other occupied port.
SSL and Non-SSL on the Same Port
Attempting to configure both HTTP and HTTPS on port 8080 causes a bind conflict with itself. Use separate ports:
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12Then redirect HTTP traffic from a different port (e.g., 8080) if needed.
Fix 6: Fix Docker Port Conflicts
When you run your Spring Boot app locally but Docker containers map to port 8080, you get the same error.
Check for containers using port 8080:
docker ps --format "table {{.Names}}\t{{.Ports}}"Look for entries like 0.0.0.0:8080->8080/tcp. Stop the conflicting container:
docker stop <container-name>Or change the host port mapping in your docker-compose.yml:
services:
myservice:
ports:
- "9090:8080" # Map host port 9090 to container port 8080If you frequently deal with Docker networking issues, the Docker “port is already allocated” guide covers more edge cases including Docker Compose, Swarm, and stale container cleanup.
Common Mistake: Running
docker-compose upin one terminal and then launching your Spring Boot app outside Docker on the same port. If yourdocker-compose.ymlmaps port 8080 to the host, your local Spring app cannot also bind to 8080. Either stop the container, change the Docker port mapping, or changeserver.portin your Spring configuration.
Fix 7: Use Profiles for Per-Environment Ports
Hardcoding a single port works for one environment, but causes conflicts when you run multiple services or deploy to different environments. Spring profiles solve this cleanly.
Create environment-specific configuration files:
application-dev.properties:
server.port=8080application-staging.properties:
server.port=8081application-prod.properties:
server.port=80Activate a profile at startup:
java -jar myapp.jar --spring.profiles.active=devOr set it as an environment variable:
SPRING_PROFILES_ACTIVE=dev java -jar myapp.jarIn your main application.properties, you can set a default profile:
spring.profiles.active=devThis approach prevents port conflicts across environments and makes your configuration explicit. Each developer on the team can use their own profile with a unique port if needed.
For YAML users, you can combine all profiles in a single application.yml:
spring:
profiles:
active: dev
---
spring:
config:
activate:
on-profile: dev
server:
port: 8080
---
spring:
config:
activate:
on-profile: staging
server:
port: 8081
---
spring:
config:
activate:
on-profile: prod
server:
port: 80Fix 8: Fix IDE-Related Issues
IDEs are one of the most common sources of “port already in use” errors during development. IntelliJ IDEA and Eclipse both have quirks that leave old processes running.
IntelliJ IDEA
Problem: You click the green “Run” button, but the previous run was never stopped. IntelliJ may or may not terminate the old process depending on your run configuration settings.
Fix: Open the Run tool window (usually at the bottom). Check if a previous instance is still listed as running. Click the red stop button to terminate it, then restart.
To prevent this from happening:
- Go to Run > Edit Configurations.
- In Before launch, check if Single instance only is enabled. If not, enable it. This ensures IntelliJ stops the old instance before starting a new one.
Alternatively, check Modify options > Allow multiple instances and make sure it is unchecked if you only want one instance running at a time.
Force-kill from IntelliJ: If the stop button does not work, open the terminal inside IntelliJ and use the OS-level kill commands from Fix 1.
Eclipse / Spring Tool Suite (STS)
Problem: Eclipse sometimes fails to terminate a Spring Boot app cleanly, especially when you use the “Relaunch” button.
Fix:
- Open the Console view.
- Click the Display Selected Console button (the monitor icon) to see all active consoles.
- Find the running Spring Boot console and click the red Terminate button.
If the process is stuck:
- Open Window > Show View > Debug.
- Right-click the lingering process and select Terminate and Remove.
VS Code with Spring Boot Extension
In VS Code, the Spring Boot Dashboard shows running applications. Stop them from the dashboard before restarting. If the dashboard does not show the process, fall back to terminal-based kill commands.
General IDE Tip
If your IDE consistently leaves zombie processes, add a shutdown hook to your application that logs the port being released. This helps you verify clean shutdowns:
@PreDestroy
public void onShutdown() {
log.info("Application shutting down, releasing port");
}When your application fails to start due to port conflicts and you also see errors about missing classes, check the ClassNotFoundException troubleshooting guide to rule out classpath issues that might cause partial startup failures.
Still Not Working?
If none of the fixes above resolved the error, check these less common causes:
Port Forwarding or VPN Conflicts
VPN software and SSH port forwarding can silently occupy ports. If you use SSH tunnels:
ssh -L 8080:remote-host:80 user@serverThis binds local port 8080 to forward traffic. Close the SSH session or change the local port in your tunnel configuration.
Check for VPN-related bindings:
lsof -i :8080 | grep -i vpnFirewall Blocking Port Release
On some systems, firewall rules or security software can hold ports in a TIME_WAIT state longer than expected. Check the port state:
netstat -an | grep 8080If you see TIME_WAIT, the OS is holding the port for a short period after the previous process closed it. Wait 30-60 seconds and try again. To reuse the port immediately, enable SO_REUSEADDR in your server configuration:
server.tomcat.reuse-address=trueCloud Deployment Port Configuration
Cloud platforms override or ignore server.port. Each platform has its own convention:
- Heroku: Uses the
PORTenvironment variable. Setserver.port=${PORT:8080}in your properties. - AWS Elastic Beanstalk: Expects port 5000 by default. Set
server.port=5000or configure the load balancer. - Google Cloud Run: Injects
PORTas an environment variable. Useserver.port=${PORT:8080}. - Azure App Service: Uses port 80 or 8080 depending on the plan. Check the platform documentation.
If your app starts fine locally but fails in the cloud, the port configuration is almost certainly the issue. Cloud platforms often route traffic through a reverse proxy, so the port your app binds to must match what the platform expects.
For Spring Boot apps that start but show a blank error page instead, that is a different issue covered in the Whitelabel Error Page guide.
Ephemeral Port Exhaustion
On heavily loaded systems running many microservices, you may run out of ephemeral ports entirely. Check your system’s available port range:
cat /proc/sys/net/ipv4/ip_local_port_rangeIf the range is too narrow, expand it:
sudo sysctl -w net.ipv4.ip_local_port_range="1024 65535"Check for Multiple Network Interfaces
If your machine has multiple network interfaces (common with Docker, VMs, or VPNs), Spring Boot binds to 0.0.0.0 by default (all interfaces). You can restrict it to a specific interface:
server.address=127.0.0.1This binds only to localhost, which may avoid conflicts with services bound to a specific external IP on the same port.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Spring BeanCreationException: Error creating bean with name
How to fix Spring BeanCreationException error creating bean caused by missing dependencies, circular references, wrong annotations, configuration errors, and constructor issues.
Fix: Java ClassCastException: class X cannot be cast to class Y
How to fix Java ClassCastException by using instanceof checks, fixing generic type erasure, resolving ClassLoader conflicts, correcting raw types, and using pattern matching in Java 16+.
Fix: Java ConcurrentModificationException
How to fix Java ConcurrentModificationException caused by modifying a collection while iterating, HashMap concurrent access, stream operations, and multi-threaded collection usage.
Fix: Java NoSuchMethodError
How to fix Java NoSuchMethodError caused by classpath conflicts, incompatible library versions, wrong dependency scope, shaded JARs, and compile vs runtime version mismatches.