1
votes

Encountered a situation where the url passed to get contains an invalid port

iex> HTTPoison.get("http://example.com:650000")

** (FunctionClauseError) no function clause matching in :inet_tcp.do_connect/4
   (kernel) inet_tcp.erl:113: :inet_tcp.do_connect({127, 0, 0, 1}, 650000, [{:packet, :raw}, {:active, false}, :binary], 8000)
   (kernel) gen_tcp.erl:185: :gen_tcp.try_connect/6
   (kernel) gen_tcp.erl:163: :gen_tcp.connect/4

Seems that I am unable to catch/rescue from this scenario.

2

2 Answers

1
votes

After digging deeper looks like the error comes from the fact that you use a port number that is bigger than the maximum accepted value.

The ports should be in range 0..65535, if we go to source code of the function that threw the exception, we can notice the following:

do_connect(Addr = {A,B,C,D}, Port, Opts, Time)
  when ?ip(A,B,C,D), ?port(Port)

I cannot find the source for ?port, however I'm sure that it checks that the port is within bounds (nonnegative and smaller than 65535).

Now the reason why you couldn't handle the error is because at some point exit() is called and process exit should be handled a little different:

try do
  result = HTTPoison.get "http://example.com:6500000"
catch
  :exit, reason -> reason
end

You encountered an error that is not handled by the HTTPoison library and is propagated to your application directly, since exit messages are propagated unless exits are trapped.

PS: You shouldn't handle errors such as this in your application unless there is no other choice.

1
votes

Use Kernel.SpecialForms.try/1.

try do
  HTTPoison.get("http://example.com:650000")
rescue
  e in [FunctionClauseError] ->
    IO.inspect(e, label: "Error")
    nil
end

#⇒ Error: %FunctionClauseError{...}