sj26/mailcatcher · error

Exception: #{exception}

Error message

    Exception: #{exception}

What it means

The second line of MailCatcher's log_exception report (lib/mail_catcher.rb:62): it prints the caught exception via string interpolation (`#{}=> exception.to_s`), giving `Class: message` — e.g. `SQLite3::SQLException: ...` or `Errno::EPIPE: Broken pipe`. This line is the actual diagnosis; the surrounding lines are context and backtrace.

Source

Thrown at lib/mail_catcher.rb:62

  def browsable?
    windows? or which? "open"
  end

  def browse url
    if windows?
      system "start", "/b", url
    elsif which? "open"
      system "open", url
    end
  end

  def log_exception(message, context, exception)
    gems_paths = (Gem.path | [Gem.default_dir]).map { |path| Regexp.escape(path) }
    gems_regexp = %r{(?:#{gems_paths.join("|")})/gems/([^/]+)-([\w.]+)/(.*)}
    gems_replace = '\1 (\2) \3'

    puts "*** #{message}: #{context.inspect}"
    puts "    Exception: #{exception}"
    puts "    Backtrace:", *exception.backtrace.map { |line| "       #{line.sub(gems_regexp, gems_replace)}" }
    puts "    Please submit this as an issue at https://github.com/sj26/mailcatcher/issues"
  end

  @@defaults = {
    :smtp_ip => "127.0.0.1",
    :smtp_port => "1025",
    :http_ip => "127.0.0.1",
    :http_port => "1080",
    :http_path => "/",
    :messages_limit => nil,
    :verbose => false,
    :daemon => !windows?,
    :browse => false,
    :quit => true,
  }

  def options

View on GitHub (pinned to 18a9cb7a79)

Solutions

  1. Identify the exception class on this line and resolve by that class: SQLite3::* -> fix gem pairing; IOError/EPIPE -> transient client disconnect, safe to ignore; NoMethodError/ArgumentError in mail parsing -> inspect the message source from the context line.
  2. Run `mailcatcher -f -v` so the report prints to your terminal instead of being swallowed by daemon mode.
  3. Search the exact exception string in https://github.com/sj26/mailcatcher/issues — recurring classes (sqlite3 null-byte, encoding) have known fixes.
  4. If unclassifiable, capture the whole block (context + exception + backtrace) and file an issue.
Defensive patterns

Strategy: try-catch

Try / catch

# Classify by the exception the report prints, then decide
begin
  MailCatcher::Mail.add_message(msg)
rescue SQLite3::Exception => e
  abort "incompatible sqlite3 for mailcatcher: #{e.message} — pin sqlite3 ~> 1.3"
rescue StandardError => e
  warn "unclassified: #{e.class}: #{e.message}" # corresponds to the printed 'Exception:' line
end

Prevention

When it happens

Trigger: Any exception swallowed by the two internal rescues: smtp.rb:62 catching failures while storing a message (SQLite3 insert errors, Mail MIME parse raising), and application.rb:89 catching failures of Faye ws.send to a dead browser connection (IOError, EPIPE). What appears here is whatever those rescues caught.

Common situations: Triaging a `451`/delivery failure reported by an SMTP client and matching it to this line; sqlite3 gem major-version incompatibility raising on message insert; browsers disconnecting (tab close, sleep) while the Bus broadcasts a new message; Ruby upgrades changing encoding behavior on binary mail parts.

Related errors


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