bobr has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

I am using Moose for several last projects of mine and I am very happy with it. Only thing is sometimes quite confusing - its error messages. Given this example:

package Cls; use Moose; has an_array => ( traits => ['Array'], isa => 'ArrayRef[Str]', is => 'rw', # !!! forgotten default to empty array handles => { list_array => 'elements', add_item => 'push', }, ); package main; func(); sub func { my $c = Cls->new(); $c->add_item('String'); }

Running code above, the error message is this:

Can't use an undefined value as an ARRAY reference at C:/Perl/site/lib/Moose/Meta/Attribute/Native/MethodProvider/Array.pm line 130.

I am looking for a way how to assume that Moose is always correct and the error is in my code (on add_item in func sub) for the sake of reporting.

I made an attempt to achieve this, but I am not very happy with the solution:

package MooseX::Silent; use Carp qw(confess); $Carp::Internal{$_}++ for qw{ MooseX::Silent MooseX::Method::Signatures::Meta::Method Moose::Meta::Attribute::Native::MethodProvider::Hash Moose::Meta::Attribute::Native::MethodProvider::Array Moose::Meta::Attribute::Native::Trait }; $SIG{'__DIE__'} = sub { my $msg = shift; for($msg) { s/^.*Internal Validation Error is: //; s/MooseX::Types::Structured:://g; s/ at .*? line \d*\.//; chomp; } confess "$msg"; }; 1;

When this module is used in the Cls class, the error message becomes:

Can't use an undefined value as an ARRAY reference at tst.pl line 22 main::func() called at tst.pl line 18

On the other hand this is pretty global and enumeration of packages is also quite inconvenient.

Is there better way to achieve similar results? Any idea or suggestion welcome.

-- thanks, Roman

Replies are listed 'Best First'.
Re: Moose warnings
by moritz (Cardinal) on May 06, 2010 at 14:05 UTC
    The long term solution is to report these error messages as bugs, and hope that the Moose developers fix them (or you can supply patches yourself).

    In my opinion any error message from inside a module is a bug, unless it clearly states how it was being misused (or unless something external goes wrong, like IO).

      The last time I mentioned those Java-style backtraces as undesirable, the #moose folks (who used same nicknames as the Moose developers usually use) said that this was intended and that huge backtraces are what you usually want.

      I think this is a sign that Moose is enterprise-ready by cargo-culting things that Java does and telling the customer that the behaviour is what they should like.

        I think this is a sign that Moose is enterprise-ready by cargo-culting things that Java does and telling the customer that the behaviour is what they should like.

        Actually, Java makes stack traces optional, you only get them if you ask for them specifically, and people usually do ask for them since it makes debugging easier. The same is true with most any language which has first class exceptions. If I had to guess though, I would suspect that printing exception stack traces on error by default originated in Smalltalk before they showed up as optional things in Java, so you got your cargo sources wrong there.

        Additionally we are not forcing this choice on our "customers" anymore (and haven't for a very long time). You can use Moose::Error::Croak if you prefer the shorter less tedious (but also less descriptive) error messages.

        As for enterprise readiness, if a few verbose stack traces can help wear away the whole perception that Perl is dead and unmaintainable, then I am all for it ;)

        -stvn
      Thanks for thoughts, I will report them.

      I was not seeing them as bugs (the error is actually in my code), but your points make a lot of sense to me.

      -- thanks, Roman

Re: Moose warnings
by stvn (Monsignor) on May 06, 2010 at 19:26 UTC

    So this particular case is likely fixable, so please do submit a bug report on it.

    Let me also say that we (the moose devs) know the error handling in Moose is not ideal and could be improved. However, Moose is unlike your typical CPAN module because of how deep it goes into your code. So while we know it is not ideal, fixing this is pretty non-trivial and so we opt to give the user the most information possible (the stack trace) rather then leaving you with not enough information.

    The real issue is that it is often very difficult for Moose to divine the intention of the user from the error condition that is thrown. And further still, the context in which the error occurs can be nowhere near the actual source of the error, and going from context to intent is often times just impossible. Doing this kind of error handling inside a library is very difficult, often times you can only get this kind of contextually sensitive error handling in a parser/lexer/compiler (and even then, not always, just ask anyone who has done any serious Haskell programming).

    So, regarding your code. There is a Moose::Error subsystem which will allow to replace the default confess stack trace with the less verbose croak or even write your own error handler (see Moose::Error::Croak for some details). For a more generic solution to the issue you might want to take a look at that.

    -stvn
      I submitted a bug report 57275 into Moose RT.

      I understand that error messages are tricky thing, especially for a library that can be (mis)used as many ways as Moose. Thats why I was a bit hesitant to submit a bug report.

      Thanks for pointing me to Moose::Error subsystem, will look into it.

      -- Roman