Turn Perl Warnings into Explanations with splain

splain turns a cryptic Perl warning into a real explanation, straight from Perl's diagnostics catalogue. It never touches the program's normal output. Ten minutes for a test run and a first pass over a real warning log.

This guide uses the installed splain from Ubuntu's Perl 5.38.2 package, version 5.38.2-3.2ubuntu0.6. The local manual is generated from that same Perl 5.38.2, and newer releases can change diagnostic wording and the diagnostics module version.

1. Check the installed command

Confirm which executable your shell will run. No elevated privileges, no changes to Perl, your script or any configuration:

$ command -v splain
/usr/bin/splain
$ dpkg-query -W -f='${Package} ${Version}\n' perl
perl 5.38.2-3.2ubuntu0.6

Checkpoint: if command -v prints nothing, the standalone filter is not on your PATH. Check the Perl package is installed, or use the diagnostics pragma inside the program instead. Do not download some unrelated program also called splain just because this one is missing.

2. Capture warnings without losing standard output

splain only reads diagnostic text; it does not run your Perl program for you. So run the program first, redirecting file descriptor 2, standard error, to a file. This harmless test throws one Perl warning and one warning from your own code:

$ tmpdir=$(mktemp -d /tmp/splain-test.XXXXXX)
$ perl -we 'use warnings; my $x; print $x + 1, "\n"; warn "manual warning\n"' \
    >"$tmpdir/program.out" 2>"$tmpdir/diag.out"
$ cat "$tmpdir/program.out"
1
$ cat "$tmpdir/diag.out"
Use of uninitialized value $x in addition (+) at -e line 1.
manual warning

Your file name and line number will differ. What matters is the split: normal output went to program.out, warnings went to diag.out. Read the raw diagnostics before transforming them, especially when a warning contains a message from your own code mixed in with Perl's.

3. Expand the captured diagnostics

Hand the captured file to splain. Its expanded output goes to standard output, so view it in the terminal or send it to a new file:

$ splain "$tmpdir/diag.out"
Use of uninitialized value $x in addition (+) at -e line 1. (#1)
    (W uninitialized) An undefined value was used as if it were already
    defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
    To suppress this warning assign a defined value to your variables.
    ...

manual warning

Here is the useful bit: the Perl warning gets a numbered explanation, but the warn from your own code stays exactly as written. That is not a bug. splain knows Perl's own diagnostic catalogue; it cannot invent an explanation for arbitrary text you pass to warn.

Warning: shell redirection with > truncates an existing file before splain even starts. Send the report somewhere new:

$ splain "$tmpdir/diag.out" >"$tmpdir/explained.out"
$ test -s "$tmpdir/explained.out" && echo "diagnostic report written"
diagnostic report written

If you overwrite a report by accident, there is no splain undo. Recovery depends entirely on your backups or filesystem history.

4. Add the diagnostics introduction when it is worth it

Use -v when whoever reads the report also needs Perl's classification guide before the individual messages. It prints a long introduction first, which makes it a poor fit for a quick terminal check or a log you already understand:

$ splain -v "$tmpdir/diag.out" >"$tmpdir/explained-with-guide.out"
$ sed -n '1,8p' "$tmpdir/explained-with-guide.out"
DESCRIPTION OF DIAGNOSTICS
    These messages are classified as follows (listed in increasing order of
    desperation):
    ...

-p requests prettier escape sequences for a pager, via the diagnostics module's PRETTY setting. Use it only if your pager and terminal actually render those sequences correctly. And keep the direction straight: the standalone filter writes to standard output, while the diagnostics pragma writes its enhanced diagnostics to standard error.

5. Keep it out of production error handling

splain is a post-processing tool. Great for a saved warning log or after a test run, useless for fixing anything: it does not validate that its suggested remedy actually fits your program. Treat the explanation as a debugging aid, then go fix the source or data condition that caused the warning.

Warning: never pipe untrusted output into a shell or treat an explanation as a command. A diagnostic file can contain arbitrary text from your program or its inputs. Reading it with splain is ordinarily unprivileged; do not reach for sudo unless you genuinely need access to a protected input or destination. Keep the original diagnostic file around when chasing a production failure, so you always have the exact warning text.

6. Use the pragma for live explanations

If you control the source and want explanations while the program runs, load the pragma near the top instead of running a second process:

use diagnostics;
use warnings;

my $value;
print $value + 1, "\n";

The pragma affects compilation as well as execution and enables Perl's -w flag. Its enhanced messages still land on standard error. On an older script this can flood you with output, so switch it on temporarily or in a focused test rather than turning it on blindly for a long-running service.

Runtime calls to disable diagnostics and enable diagnostics control the pragma at runtime, but not compile-time diagnostics. If the failure is a fatal error and you need a call stack rather than warning explanations, rerun with -Mdiagnostics=-traceonly. Add -warntrace for warning stack traces too:

$ perl -Mdiagnostics=-traceonly my_script.pl
$ perl -Mdiagnostics=-warntrace my_script.pl

Warning: both of those commands rerun the script. If it sends mail, writes files or talks to a service, use a safe test copy or the service's normal maintenance procedure first. splain itself only ever reads a diagnostic file and writes a report; it is the script rerun that carries the real risk.

Done means