Skip to content

Fix: Spring Boot Web server failed to start. Port 8080 was already in use

FixDevs ·

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 use
org.apache.catalina.LifecycleException: Protocol handler start failed
Caused by: java.net.BindException: Address already in use: bind

The 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 -jar process 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 httpd or 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 :8080

You 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 12345

If it does not stop, force-kill it:

kill -9 12345

One-liner to find and kill in a single command:

lsof -ti :8080 | xargs kill -9

You can also use fuser on Linux:

fuser -k 8080/tcp

Windows

Find the process:

netstat -ano | findstr :8080

Sample output:

TCP    0.0.0.0:8080    0.0.0.0:0    LISTENING    12345

The last column is the PID. Kill it:

taskkill /PID 12345 /F

Or use PowerShell for a cleaner approach:

Get-NetTCPConnection -LocalPort 8080 | Select-Object OwningProcess
Stop-Process -Id 12345 -Force

After 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=8081

Using application.yml

If you use YAML configuration:

server:
  port: 8081

Using a Command-Line Argument

Override the port at startup without changing any files:

java -jar myapp.jar --server.port=8081

Using an Environment Variable

Set the port through the SERVER_PORT environment variable:

SERVER_PORT=8081 java -jar myapp.jar

On Windows:

set SERVER_PORT=8081
java -jar myapp.jar

Pick 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 8081 for service A, 8082 for 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=0

This 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 java

On Windows:

tasklist | findstr java

You 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 --stop

Check 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=1000

If 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=8081

Make 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.p12

Then 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 8080

If 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 up in one terminal and then launching your Spring Boot app outside Docker on the same port. If your docker-compose.yml maps port 8080 to the host, your local Spring app cannot also bind to 8080. Either stop the container, change the Docker port mapping, or change server.port in 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=8080

application-staging.properties:

server.port=8081

application-prod.properties:

server.port=80

Activate a profile at startup:

java -jar myapp.jar --spring.profiles.active=dev

Or set it as an environment variable:

SPRING_PROFILES_ACTIVE=dev java -jar myapp.jar

In your main application.properties, you can set a default profile:

spring.profiles.active=dev

This 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: 80

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:

  1. Go to Run > Edit Configurations.
  2. 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:

  1. Open the Console view.
  2. Click the Display Selected Console button (the monitor icon) to see all active consoles.
  3. Find the running Spring Boot console and click the red Terminate button.

If the process is stuck:

  1. Open Window > Show View > Debug.
  2. 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@server

This 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 vpn

Firewall 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 8080

If 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=true

Cloud Deployment Port Configuration

Cloud platforms override or ignore server.port. Each platform has its own convention:

  • Heroku: Uses the PORT environment variable. Set server.port=${PORT:8080} in your properties.
  • AWS Elastic Beanstalk: Expects port 5000 by default. Set server.port=5000 or configure the load balancer.
  • Google Cloud Run: Injects PORT as an environment variable. Use server.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_range

If 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.1

This binds only to localhost, which may avoid conflicts with services bound to a specific external IP on the same port.

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