hashicorp/vagrant · error · Vagrant::Errors::ForwardPortCollision

Vagrant cannot forward the specified ports on this VM, since

Error message

Vagrant cannot forward the specified ports on this VM, since they
would collide with some other application that is already listening
on these ports. The forwarded port to %{host_port} is already in use
on the host machine.

To fix this, modify your current project's Vagrantfile to use another
port. Example, where '1234' would be replaced by a unique host port:

  config.vm.network :forwarded_port, guest: %{guest_port}, host: 1234

Sometimes, Vagrant will attempt to auto-correct this for you. In this
case, Vagrant was unable to. This is usually because the guest machine
is in a state which doesn't allow modifying port forwarding. You could
try 'vagrant reload' (equivalent of running a halt followed by an up)
so vagrant can attempt to auto-correct this upon booting. Be warned
that any unsaved work might be lost.

What it means

The handle_forwarded_port_collisions middleware checks each forwarded host port against ports already forwarded within this environment, an external port checker, and DHCP lease reservations. If the port is in use and repair is impossible (auto_correct not enabled for this port, or `repair` mode off), it raises ForwardPortCollision naming the colliding host port.

Source

Thrown at lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb:131

            if options[:protocol] && options[:protocol] != "tcp"
              @logger.debug("Skipping #{host_port} because UDP protocol.")
              next
            end

            if remap[host_port]
              remap_port = remap[host_port]
              @logger.debug("Remap port override: #{host_port} => #{remap_port}")
              host_port = remap_port
            end

            # If the port is open (listening for TCP connections)
            in_use = is_forwarded_already(extra_in_use, host_port, host_ip) ||
              call_port_checker(port_checker, host_ip, host_port) ||
              lease_check(host_ip, host_port)

            if in_use
              if !repair || !options[:auto_correct]
                raise Errors::ForwardPortCollision,
                  guest_port: guest_port.to_s,
                  host_port:  host_port.to_s
              end

              @logger.info("Attempting to repair FP collision: #{host_port}")

              repaired_port = nil
              while !usable_ports.empty?
                # Attempt to repair the forwarded port
                repaired_port = usable_ports.to_a.sort[0]
                usable_ports.delete(repaired_port)

                # If the port is in use, then we can't use this either...
                in_use = is_forwarded_already(extra_in_use, repaired_port, host_ip) ||
                  call_port_checker(port_checker, host_ip, repaired_port) ||
                  lease_check(host_ip, repaired_port)
                if in_use
                  @logger.info("Repaired port also in use: #{repaired_port}. Trying another...")

View on GitHub (pinned to 35f3160f4a)

Solutions

  1. Free the port: find the listener with `lsof -nP -iTCP:HOST_PORT -sTCP:LISTEN` (or `netstat -ano | findstr :HOST_PORT` on Windows) and stop it.
  2. Or change to a unique host port in the Vagrantfile (`host: 18080`).
  3. Or opt into auto-correction: add `auto_correct: true` to that forwarded_port declaration so Vagrant picks a free port from the correction range.
  4. If auto-correct was already on but failed because the machine was running, `vagrant reload` lets Vagrant repair the collision at boot.

Example fix

# before
config.vm.network "forwarded_port", guest: 80, host: 8080  # 8080 already used on host

# after
config.vm.network "forwarded_port", guest: 80, host: 18080
# or let Vagrant pick a free host port:
config.vm.network "forwarded_port", guest: 80, host: 8080, auto_correct: true
Defensive patterns

Strategy: validation

Validate before calling

# Ruby: assert the host port is free before `vagrant up`
require "socket"
def port_free?(ip, port)
  s = TCPServer.new(ip, port)
  s.close
  true
rescue Errno::EADDRINUSE, Errno::EACCES
  false
end
abort "host port 8080 busy" unless port_free?("0.0.0.0", 8080)

Prevention

When it happens

Trigger: `vagrant up`/`vagrant reload` with a `config.vm.network "forwarded_port", guest: G, host: H` where H is already listening on the host (another VM, Docker container, local dev server) and the port lacks `auto_correct: true` (lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb:126-134).

Common situations: Several Vagrant projects competing for the default SSH port 2222; a local web server already on 8080; Docker publishing the same port; the message's auto-correct path failing because the guest is in a state that does not allow re-configuring forwarding (then `vagrant reload` lets it retry at boot).

Related errors


AI-assisted analysis of hashicorp/vagrant@35f3160f4a (2026-08-21). Data as JSON: /api/errors/98759b7db0ddb3f0. Report an issue: GitHub.