ZetCode

Perl error handling

last modified October 8, 2026

In this article we show how to handle errors in Perl. We cover die and warn, eval blocks and string eval, checking $@, the or die idiom with $!, exceptions as objects or hashrefs, and the __DIE__ and __WARN__ handlers set through %SIG.

Perl reports runtime problems in two ways: non-fatal conditions are reported with warn, and fatal errors are raised with die. A die stops the program unless the error is caught by an eval.

Perl die and eval

In the first example, we catch an error raised by die inside an eval block.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

my $result = eval {
    die "Something went wrong\n";
    1;
};

if (!$result) {
    print "Caught error: $@";
}

say "Program continues";

The eval block runs the code inside it. If the code dies, the block is aborted, eval returns undef, and the error message is stored in the $@ variable.

my $result = eval {
    die "Something went wrong\n";
    1;
};

We place the code that may fail inside the block. The final 1 is reached only when no error occurs, so the block returns a true value on success.

if (!$result) {
    print "Caught error: $@";
}

We check the result of the eval. If it failed, we print the message stored in $@. The message ends with a newline, so die does not append the file name and line number.

$ ./main.pl
Caught error: Something went wrong
Program continues

Perl or die with $!

The or die idiom is the usual way to stop when a system call fails. The $! variable holds the operating system error message from the last failed call.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

open my $fh, "<", "missing.txt"
    or die "Cannot open missing.txt: $!";

say "This line is not reached";

We try to open a file that does not exist. The open call returns false, so die runs and terminates the program. Since the message does not end with a newline, Perl appends the file name and line number.

$ ./main.pl
Cannot open missing.txt: No such file or directory at main.pl line 6.

Perl warn

warn prints a message to standard error and lets the program continue. It is used for problems that are not serious enough to stop the program.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

warn "Configuration value is missing\n";
warn "Using default value";

say "Program continues";

Both warn calls write to standard error. The second message does not end with a newline, so Perl adds the file name and line number. Execution then continues normally.

$ ./main.pl
Configuration value is missing
Using default value at main.pl line 7.
Program continues

Perl nested eval

An eval can be placed inside another one. An error caught by the inner eval does not reach the outer one, unless it is raised again.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

eval {
    eval {
        die "inner failure\n";
    };
    print "Inner eval caught: $@";

    die "outer failure\n";
};
print "Outer eval caught: $@";

The inner eval catches its own error and the outer block goes on. The outer block then dies with a new message, which the outer eval catches.

$ ./main.pl
Inner eval caught: inner failure
Outer eval caught: outer failure

Perl die with a hashref

The argument to die does not have to be a string. We can pass a reference, such as a hashref, that carries structured information about the error. Objects can be used in the same way.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

eval {
    die { code => 404, message => "Page not found" };
};

if (ref $@ eq 'HASH') {
    say "Error code: $@->{code}";
    say "Message: $@->{message}";
}

When die receives a reference, $@ holds that same reference. We use ref to check its type before accessing the fields. Using a reference avoids parsing error strings to find out what went wrong.

$ ./main.pl
Error code: 404
Message: Page not found

Perl local $@

$@ is a global variable. Any eval that runs, including one inside a called function, overwrites it. If a function uses eval for its own cleanup, it can hide an error that the caller has not yet read. To prevent this, we localize $@ inside such functions.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

sub cleanup {
    local $@;
    eval { die "cleanup failed\n" };
}

eval { die "real error\n" };
cleanup();
print "Error still: $@";

The local $@ line saves the value of $@ and restores it when the function returns. The eval inside cleanup still sets $@, but the caller sees the original error.

$ ./main.pl
Error still: real error

Perl __WARN__ handler

The %SIG hash lets us install handlers for warnings and fatal errors. The __WARN__ handler is called instead of printing the warning to standard error. This is useful for logging warnings or turning them into errors.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

local $SIG{__WARN__} = sub {
    my $msg = shift;
    print "Intercepted warning: $msg";
};

warn "Disk space is low\n";
my $undef;
my $n = 5 + $undef;

say "Result: $n";

The handler receives the warning text as its first argument. It is called for explicit warn calls and for warnings generated by Perl itself, such as the use of an undefined value in an addition.

$ ./main.pl
Intercepted warning: Disk space is low
Intercepted warning: Use of uninitialized value $undef in addition (+) at main.pl line 13.
Result: 5

Perl __DIE__ handler

The __DIE__ handler is called whenever die is invoked, including inside an eval. The handler runs before the error is handed to $@. It is often used to add a stack trace or to log errors. The handler should not swallow the error; if it returns, the die continues.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

local $SIG{__DIE__} = sub {
    my $msg = shift;
    print "Handler saw: $msg";
};

eval {
    die "Fatal problem\n";
};

say "Recovered, \$@ is: $@";

The handler is called with the message before eval catches it. After the eval finishes, the program continues and $@ still contains the message.

$ ./main.pl
Handler saw: Fatal problem
Recovered, $@ is: Fatal problem

Perl string eval

A string eval compiles and runs Perl code given as a string. Syntax errors in the string do not stop the program; they are stored in $@ just like runtime errors.

main.pl
#!/usr/bin/perl

use v5.34.0;
use warnings;

my $code = '1 +';
my $result = eval $code;

if ($@) {
    print "String eval failed: $@";
} else {
    say "Result: $result";
}

my $ok = eval "2 * 21";
say "Good eval result: $ok";

The first string is incomplete, so Perl reports a syntax error and eval returns undef. The second string is valid, and its value is returned as usual. Because the code is compiled at run time, string eval should be used with care, especially with input from users.

$ ./main.pl
String eval failed: syntax error at (eval 1) line 1, at EOF
Good eval result: 42

Try::Tiny

eval has some pitfalls: $@ must be checked right away, and a local $@ is needed in cleanup code. The Try::Tiny module from CPAN provides try and catch blocks that handle these details. It is not part of the Perl core and is not required for anything in this article; the examples above use only eval, die, and warn.

Best Practices

Source

Perl die Documentation

Perl eval Documentation

In this article we have covered error handling in Perl, including die, warn, eval, $@, and the %SIG handlers.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Perl tutorials.