Global symbol requires explicit package name

Global symbol requires explicit package name is a common, and IMHO very misleading error message of Perl. At least for beginners.

The quick translation is "You need to declare the variable using my."

The simplest example


  use strict;
  use warnings;

  $x = 42;

And the error is


  Global symbol "$x" requires explicit package name at ...

While the actual error message is correct, this is little use for the beginner Perl programmer. They have probably not learned what packages are. Nor do they know what can be more explicit than $x ?

This error is generated by use strict. The explanation in the documentation is:

This generates a compile-time error if you access a variable that wasn't declared via "our" or "use vars", localized via "my()", or wasn't fully qualified.

A beginner will hopefully start every script with use strict and will probably learn about my before any of the other possibilities.

I don't know if the actual text can and should be changed in perl. That's not the point of this post. The point is to help beginners understand in their own language what does this error message mean.

So the solution in the above case is to write


  use strict;
  use warnings;

  my $x = 42;

The bad solution

The other "solution" is to remove strict:


  #use strict;
  use warnings;

  $x = 23;

that would work but this code will generate a Name "main::x" used only once: possible typo at ... warning.

In any case, you would not drive a car without the safety belt, would you?

Example 2: scope

Another case I often see with beginners looks like this:


  use strict;
  use warnings;

  my $x = 1;

  if ($x) {
  my $y = 2;
  }

  print $y;

The error we get is


  Global symbol "$y" requires explicit package name at ...

which is surprising for some people. Especially when they start their coding. After all they declares $y using my.

First, there is a little visual problem. The indentation of my $y = 2; is missing. If it was indented a few spaces or a tab to the right, as in the next example, the source of the problem might be more obvious:


  use strict;
  use warnings;

  my $x = 1;

  if ($x) {
      my $y = 2;
  }

  print $y;

The problem is that the variable $y is declared within the block (the pair of curly braces) which means they do not exists outside of that block. This is called the scope of the variable. The whole idea is scope is different among programming languages. In Perl, a block creates a scope. What is declared inside using "my" will not be accessible outside the block.

(BTW the $x = 1 is there only to have a legitimate-looking condition that creates the scope.)

The solution is either to call the print inside the block:


  use strict;
  use warnings;

  my $x = 1;

  if ($x) {
      my $y = 2;
      print $y;
  }

or to declare the variable outside the block (and not inside!):


  use strict;
  use warnings;

  my $x = 1;
  my $y;
  
  if ($x) {
      $y = 2;
  }

  print $y;

Of course if we forget to remove the my from the inside or if $x is false, then we get a Use of uninitialized value warning.

The other ways

Explaining what our and use vars do or how can one fully qualify a variable name is left to another post.


Perl tutorial and video course

For further articles see the Beginner Perl Maven tutorial book and video course.


In the comments, please wrap your code snippets within <pre> </pre> tags and use spaces for indentation.
blog comments powered by Disqus
Online courses:


Would you like to get
updated when I publish
the next article?

Follow me:

Google Plus Twitter RSS feed