ruby/ruby · error · InvalidComponentError

missing opaque part for mailto URL

Error message

missing opaque part for mailto URL

What it means

URI::Mailto must carry an opaque part holding the addr-spec; the RFC 3986 parser does not populate opaque for mailto, so initialize derives it from the query or expects it set. With neither opaque nor query — i.e., no address at all — initialize raises InvalidComponentError 'missing opaque part for mailto URL'.

Source

Thrown at lib/uri/mailto.rb:142

    # == Description
    #
    # Creates a new URI::MailTo object from generic URL components with
    # no syntax checking.
    #
    # This method is usually called from URI::parse, which checks
    # the validity of each component.
    #
    def initialize(*arg)
      super(*arg)

      @to = nil
      @headers = []

      # The RFC3986 parser does not normally populate opaque
      @opaque = "?#{@query}" if @query && !@opaque

      unless @opaque
        raise InvalidComponentError,
          "missing opaque part for mailto URL"
      end
      to, header = @opaque.split('?', 2)
      # allow semicolon as a addr-spec separator
      # http://support.microsoft.com/kb/820868
      unless /\A(?:[^@,;]+@[^@,;]+(?:\z|[,;]))*\z/ =~ to
        raise InvalidComponentError,
          "unrecognised opaque part for mailtoURL: #{@opaque}"
      end

      if arg[10] # arg_check
        self.to = to
        self.headers = header
      else
        set_to(to)
        set_headers(header)
      end
    end

View on GitHub (pinned to 0e5b888e1c)

Solutions

  1. Skip link generation when the address is blank
  2. Build with a real address: URI::Mailto.build(['user@example.com', 'subject=Hi'])
  3. Presence-validate the email before any URI parsing

Example fix

# before
uri = URI("mailto:#{params[:email]}")   # params[:email] nil -> "mailto:"
# InvalidComponentError: missing opaque part for mailto URL

# after
email = params[:email].to_s.strip
return if email.empty?
uri = URI("mailto:#{email}")
Defensive patterns

Strategy: validation

Validate before calling

def mailto_uri(email)
  email = email.to_s.strip
  return nil if email.empty?
  URI("mailto:#{email}")
end

Try / catch

begin
  URI("mailto:#{email}")
rescue URI::InvalidComponentError
  nil # blank address -> no link
end

Prevention

When it happens

Trigger: URI('mailto:'); URI::Mailto.build([nil, nil]); URI::Mailto.new with all blank components — the classic producer is URI("mailto:#{email}") with email nil or empty.

Common situations: Building mailto links from optional form fields; templates rendering mailto with an empty address variable; contact forms where the email param is missing.

Related errors


AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21). Data as JSON: /api/errors/1414f1baa5232f9d. Report an issue: GitHub.