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.
#!/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.
#!/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.
#!/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.
#!/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.
#!/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.
#!/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.
#!/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.
#!/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.
#!/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
- Check eval results: Always test the result or
$@after aneval. - Add newlines: End messages with
\nwhen you do not want the file name and line number appended. - Use local $@: Protect the caller's error when cleanup code uses
eval. - Prefer references for details: Die with a hashref or object when callers need structured information.
- Use $! in system calls: Include the reason from
$!when a file or system operation fails.
Source
In this article we have covered error handling in Perl, including
die, warn, eval, $@,
and the %SIG handlers.
Author
List all Perl tutorials.