Error reports/messages: what does this error message mean and can it be improved?

43 views
Skip to first unread message

Sasha Fonseca

unread,
Dec 17, 2016, 6:15:10 AM12/17/16
to Lisp Flavoured Erlang
Hello LFE Group, 

I've recently started learning LFE. I've got about a year a year/year and a half experience with Erlang and Elixir (90% Elixir), and I don't recall ever seeing this kind of error message before:

=ERROR REPORT==== 16-Dec-2016::16:18:43 ===
Error in process <0.75.0> on node messenger@Ubuntu with exit value:
{undef,[{messenger,server,[],[]}]}

 This is from the trying to run the messenge.lfe example from the tutorial. 
  • What's the meaning behind this error? 
  • Could the error report somehow be improved? 
  • How can I begin to debug it? 
  • Is this a LFE specific error or BEAM in general?
  • Are these simple error messages an intended language feature?

I've been finding LFE's error messages to be quite lackluster. For example, sometimes the line relative to the error is shown as '99999' which obviously is incorrect since my programs so far have had 50 lines tops. Another example is this 'illegal guard' error:

./tut7.lfe:13: illegal guard


and then compare it to Elixir's:

== Compilation error on file test.ex ==
** (CompileError) test.ex:2: cannot invoke local is_bar/1 inside guard
** (exit) shutdown: 1
   
(elixir) lib/kernel/parallel_compiler.ex:291: Kernel.ParallelCompiler.handle_failure/3
   
(elixir) lib/kernel/parallel_compiler.ex:247: Kernel.ParallelCompiler.wait_for_messages/1
   
(elixir) lib/kernel/parallel_compiler.ex:62: Kernel.ParallelCompiler.spawn_compilers/3
       
(iex) lib/iex/helpers.ex:142: IEx.Helpers.c/2


The (CompileError) line shows what's the source of the problem and why it was raised. The stack trace does not really add a lot to it in this case (but it does not hurt either). I believe it also makes the language and it's environment look as being more mature and solid for development since it's giving good, succinct and explicit feedback to the user.

I'm not badmouthing LFE with this post. I'm just giving my feedback as a new user of the language :)

Sasha Fonseca

unread,
Dec 17, 2016, 7:34:58 AM12/17/16
to Lisp Flavoured Erlang
Another example of insufficient detail in the error report:

(cutler@Zane)lfe> (c "tut20.lfe")
./tut20.lfe:8: bad form: application
./tut20.lfe:8: unbound symbol: n
./tut20.lfe:8: unbound symbol: n


(defun ping1
 
((0 pong-pid)
   
(exit 'ping)
  ((n pong-pid)
   (! pong-pid (tuple '
ping (self))))
   
(receive
     
('pong (lfe_io:format "Ping received pong ~p~n" (list n))))
   (ping1 (- n 1) pong-pid)))

There's an error in line 8, which is '(defun ping1' about two unbound symbol 'n'. Alright I can infer it's probably the one in the recursive call and the one in the string, but couldn't those two actual lines be printed instead of the function def? This is easy to debug in such a small function but I imagine it could be quite the head cracker in a more complex one. I realize the error is the first function clause not being properly closed.

Eric Bailey

unread,
Dec 17, 2016, 1:14:01 PM12/17/16
to lisp-flavo...@googlegroups.com
Thanks for the constructive feedback! Keep it coming.

I agree the error messages can be frustrating. Improving them has been on the radar awhile now, but a few other initiatives are taking precedence, such as shoring up Hex support and adding types. Early in the new year, I/we should be able to take a crack at starting to improve the error messages. I'm not an Elixir user, but I quite like Elm's error messages and their attitude toward them in general.

Eric




--
You received this message because you are subscribed to the Google Groups "Lisp Flavoured Erlang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-e...@googlegroups.com.
To post to this group, send email to lisp-flavo...@googlegroups.com.
Visit this group at https://groups.google.com/group/lisp-flavoured-erlang.
For more options, visit https://groups.google.com/d/optout.

Duncan McGreggor

unread,
Dec 17, 2016, 1:14:22 PM12/17/16
to Lisp Flavoured Erlang
Yeah, this is probably one of the most glaring issues in LFE. (Not unlike Clojure, in that regard! Every year the Clojure survey puts "need better errors!" at or close to the top of user feedback ... and LFE is much worse than Clojure for it's error message ... opacity).

I often forget what the early stages of learning a given language were like for me ... they just tend to fade into the background. But I still remember the months of head-scratching I went through when I first started using LFE. It reminded me of my time using Mathematica two decades prior ...

I picked up LFE first, and when I started to learn Erlang, some of those error messages began making more sense. The most frustrating thing was when I finally *did* figure out what a message *really* meant, I couldn't remember the convoluted path I took to get there, and almost never remembered the end result ... lots of repeated discovery. I did find that as I exercised better practices from Erlang failure-handling, the messages occurred less often and those that did arise made more sense (not magic; handling errors properly in BEAM languages means you/your apps have a better context in which to view and understand the errors).

Though I can't offer any immediate solution to the poor error messages, one of the biggest recommendations I can make that will mitigate them is: keep your functions small. Break up the logic into sensibly named task-specific functions. The superficial benefit you get is that the stack traces will be a little more self-documenting. The more profound benefit is that your code becomes more concise, easier to reason about, easier to maintain and update, and -- most pertinent to this discussion -- far, far easier to debug (due to the improved logical clarity and separation of concerns). Sorry, I know this is all basic stuff, but it often bears repeating :-) (Hell, I have to repeat it to myself, sometimes ...)

In your first email of this thread, I have see that error message a bunch both in Erlang and LFE when I have made any number of mistakes that prevent the remote node from being able to find the given function (everything from typos, to unexported functions, to improper use of remote calling, etc.)

In that same email, your comparison to Elxir's error message is an excellent demonstration of what's lacking. While I don't notice this *too* much anymore, since I make extensive use of lager and trace/debug/info/etc calls (and setting log levels during development), I do find this is still a general problem that needs to be solved in LFE. It would be fantastic if we could improve the stack traces. This does get a bit tricky in LFE, since line numbers of individual failures aren't tracked (only the line number where a function begins).

In your second email of this thread, it looks like the error is due to a missing paren at the end of the function's first clause. That would cause what should be the second clause to instead be interpreted as a bad form (double-parens like that aren't valid in non-clause situations -- if it's a list, it needs to be quoted; if it's an attempted call like you do in a Lisp-1, you'd need to use funcall instead). application as well as not having the n variable actually get bound (thus an error for the recieve and an error for the call to ping1 at the end).

Keep the suggestions and feedback coming!

d



--
You received this message because you are subscribed to the Google Groups "Lisp Flavoured Erlang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-erlang+unsub...@googlegroups.com.
To post to this group, send email to lisp-flavoured-erlang@googlegroups.com.

Robert Virding

unread,
Dec 18, 2016, 7:21:26 AM12/18/16
to Lisp Flavoured Erlang
OK, more direct replies to your questions:

The first error message you mention comes from the Erlang system. It can either have been sent from the machine itself (yes, for some strange reason it generates error messages when some, only some, processes die) or come from the standard erlang error logger. LFE does not replace or supplement the standard Erlang error logger so you see what standard erlang users see.

The 'undef' error means that a fully qualified call to a function could not be made either because the module wasn't or couldn't be loaded or because the function wasn't exported. In this case messenger:server/0.

In the second case, yes the LFE compiler error reporting is a bit sparse. I am working on improving it. One thing I cannot improve is the line numbering as the language is truly iconic so their is no AST with line numbers. The only line number I know is the one of the first line of the function. Unfortunately macros make it worse as the error can occur in code you have not written and don't know it exists.

Personally I find the elixir compiler stacktrace irritating as it it totally irrelevant information unless you are developing the compiler. :-)

Robert

Robert Virding

unread,
Dec 18, 2016, 7:40:10 AM12/18/16
to Lisp Flavoured Erlang
This is a tricky one.

Seeing lisp doesn't really have a syntax, or a very simple one depending on your POV, the compiler has no way of detecting that a parentheses is missing to end the clause. All it sees is another call in the body and when it checks it it sees that "function" part of the form is illegal. Hence the error message. As their is no 2nd clause with a pattern defining 'n' you get the unbound symbol error.

There is not much I can do to catch this type of error except improve the error messages, maybe include the part of the form which was wrong.

Robert

Mário Guimarães

unread,
Dec 22, 2016, 7:48:19 AM12/22/16
to lisp-flavo...@googlegroups.com
Hi Robert,


"One thing I cannot improve is the line numbering as the language is truly iconic so their is no AST with line numbers. The only line number I know is the one of the first line of the function. "

What you mean by "truly iconic" ?

Why can't you annotate the AST with line numbers? Isn't this done in other Lisps?

Just want to have a clear idea of what is going on, as this seems to me very limiting of better error processing and debugging.

Thanks
Mário



--

Robert Virding

unread,
Dec 22, 2016, 8:03:20 AM12/22/16
to Lisp Flavoured Erlang
The problem is that there is no AST. In lisp there is no difference between code and data, code is just data, so the function definition:

(defun add-2 (x y) (+ x y 2))

is just the list. Whether it is code or data depends on how I want to interpret it. This is what being homoiconic is all about. This is what makes it so easy in lisp to write code which generates code, for example macros.

Robert

Mário Guimarães

unread,
Dec 22, 2016, 8:15:57 AM12/22/16
to lisp-flavo...@googlegroups.com
Right, but isn't Lisp source code also its AST?
If so, which I believe it is, then I do not see why we can't have line numbers for every function call ...

For example, why can't LFE load the whole source file in a tree in memory, attach it line numbers, expand macros, all this resulting in a new tree in memory, and at the end, compile everything to .beam or whatever? What is the problem with this?

Or, how is LFE doing what it does to compile its source, so that it cannot have line numbers everywhere?

Sorry if I am boring you, but this is something interesting to me.

Mário

Reply all
Reply to author
Forward
0 new messages