[erlang-questions] why is the error reason in a catch/try truncated?

Raimo Niskanen <>
Tue Jan 18 16:46:21 CET 2011


On Tue, Jan 18, 2011 at 03:52:15PM +0100, Joe Armstrong wrote:
> I have a program.
> 
> When I run the "uncaught" version it prints a very nice error message like
> this:
> 
> > compile_file(File, Args, ParseTree).
> 
> {"init terminating in
> do_boot",{badarg,[{lists,member,[free_index,all_keys]},{ecc_db,add_to_list,2},{ecc_db,store,2},{ecc_pass1,start,2},{ecc_compile,compile_file0,3},{ecc_compile,compile_file,3},{ecc,batch,1},{init,start_it,1}]}}
> 
> This tells be exactly were I bombed.
> 
> In my "production" version of the code I add wrapper with a catch/try to
> trap any unwanted errors.
> So I write:
> 
> compile_file(File, Args, ParseTree) ->
>  case (catch compile_file0(File, Args, ParseTree)) of
>     {'EXIT', Why} ->
>         io:format("Compile file:~s aborted with:~p ~n",[File, Why]);
>     _ ->
>         ok
>     end
> 
> But when i run this
> 
> > compile_file(File, Args, ParseTree).
> Compile file:first.c aborted with:error badarg
> 
> So the Why in the error tuple has lost all the useful information that was
> in
> the untrapped code.
> 
> To find the error I have to comment out the wrapped version and
> run the unwrapped version. This is because Why is just the atom
> badarg and not the more verbose {badarg, ...}
> 
> I find this behavior very unhelpfull - am I the only one?

You must be doing something wrong.

$ cat test.erl
-module(test).
-export([foo/2]).
foo(T, L) ->
    catch lists:member(T, L).

$ erl
Erlang R14B01 (erts-5.8.2) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]

Eshell V5.8.2  (abort with ^G)
1> test:foo(d, [a,b,c|q]).
{'EXIT',{badarg,[{lists,member,[d,[a,b,c|q]]},
                 {test,foo,2},
                 {erl_eval,do_apply,5},
                 {shell,exprs,7},
                 {shell,eval_exprs,7},
                 {shell,eval_loop,3}]}}

The catch operator returns the whole stackdump.

If you used the try..catch construct as your subject indicated
but not your code, it will exclude the stacktrace, which is
the intended behaviour since constructing the stacktrace
will cost performance. To get the stacktrace in a try..catch
you can use erlang:get_stacktrace(). See
http://erlang.org/doc/reference_manual/expressions.html, section "Try"
especially the example: Using try to emulate catch Expr:
  try Expr
  catch
      throw:Term -> Term;
      exit:Reason -> {'EXIT',Reason}
      error:Reason -> {'EXIT',{Reason,erlang:get_stacktrace()}}
  end

> 
> 
> /Joe

-- 

/ Raimo Niskanen, Erlang/OTP, Ericsson AB


More information about the erlang-questions mailing list