sj26/mailcatcher · error

~~> ERROR: Something's using port #{port}. Are you already r

Error message

~~> ERROR: Something's using port #{port}. Are you already running MailCatcher?

What it means

MailCatcher failed to bind one of its two listeners (SMTP on 1025 or HTTP on 1080 by default) because the port is already taken. EventMachine raises only a bare RuntimeError with the text 'no acceptor', which rescue_port pattern-matches at lib/mail_catcher.rb:243, prints this message, and exits the process with status -1. Despite the wording, anything occupying the port triggers it, not just another MailCatcher instance.

Source

Thrown at lib/mail_catcher.rb:244

protected

  def smtp_url
    "smtp://#{@@options[:smtp_ip]}:#{@@options[:smtp_port]}"
  end

  def http_url
    "http://#{@@options[:http_ip]}:#{@@options[:http_port]}#{@@options[:http_path]}".chomp("/")
  end

  def rescue_port port
    begin
      yield

    # XXX: EventMachine only spits out RuntimeError with a string description
    rescue RuntimeError
      if $!.to_s =~ /\bno acceptor\b/
        puts "~~> ERROR: Something's using port #{port}. Are you already running MailCatcher?"
        puts "==> #{smtp_url}"
        puts "==> #{http_url}"
        exit -1
      else
        raise
      end
    end
  end
end

View on GitHub (pinned to 18a9cb7a79)

Solutions

  1. Find and stop the existing process: `lsof -i :1025 -i :1080` (or `ss -ltnp | grep -E '1025|1080'`), then kill the listed PID — or quit the old MailCatcher via DELETE http://127.0.0.1:1080/ from its web UI.
  2. If the occupier is another MailCatcher you want gone: `pkill -f mailcatcher` or kill the daemon PID.
  3. Run on different ports: `mailcatcher --smtp-port 1026 --http-port 1081`, and point your app's SMTP delivery at the new port.
  4. If you actually need two instances, give each its own --ip/--smtp-port/--http-port combination.

Example fix

# before
mailcatcher
# ~~> ERROR: Something's using port 1080. Are you already running MailCatcher?

# after (option 1: free the port)
lsof -ti :1025 -ti :1080 | xargs kill
mailcatcher

# after (option 2: pick free ports)
mailcatcher --smtp-port 1026 --http-port 1081
# then configure the app's SMTP client for localhost:1026
Defensive patterns

Strategy: validation

Validate before calling

# Ruby: verify MailCatcher's ports are free before spawning it
require "socket"

def port_free?(ip, port)
  sock = TCPServer.new(ip, port)
  true
rescue Errno::EADDRINUSE, Errno::EACCES
  false
ensure
  sock&.close
end

smtp_port, http_port = 1025, 1080
unless port_free?("127.0.0.1", smtp_port) && port_free?("127.0.0.1", http_port)
  abort "port busy: pick others, e.g. mailcatcher --smtp-port #{smtp_port + 1} --http-port #{http_port + 1}"
end
# shell alternative: lsof -i :1025 -i :1080

Prevention

When it happens

Trigger: Starting `mailcatcher` when a previous daemonized instance is still running; another app bound to 1025/1080 (e.g. a dev SMTP server, nginx, or another Rails app's mailcatcher); starting MailCatcher twice in CI or docker-compose without unique ports; passing --smtp-port/--http-port (or --ip) values that collide with an existing listener, since both servers are started inside the single EventMachine.run loop (lib/mail_catcher.rb:182,189).

Common situations: MailCatcher daemonizes by default on non-Windows (:daemon => !windows?), so a forgotten background process silently holds the ports; two developers sharing a machine/VM; Docker containers with mirrored host ports; a crashed run whose socket lingers; ports below 1024 chosen without root.

Related errors


AI-assisted analysis of sj26/mailcatcher@18a9cb7a79 (2026-08-21). Data as JSON: /api/errors/e43e09d5448c9a9c. Report an issue: GitHub.