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

I'm running tests which are in a ./t subdirectory. Tests are failing with "Can't locate so-and-so in @INC", despite the fact that the missing module is in the first directory named in the dump of @INC. I have $PERL5LIB set. Thus:

# echo $PERL5LIB /home/henry/gitr/MAS/lib # prove ./t/8bit.t ./t/8bit.t .. Can't locate MAS::Global in @INC (@INC entries checked: +/home/henry/gitr/MAS/lib /etc/perl (... others omitted) # find /home/henry/gitr/MAS/lib -name Global.pm /home/henry/gitr/MAS/lib/MAS/Global.pm # It's in $INC[0] # perl -c /home/henry/gitr/MAS/lib/MAS/Global.pm /home/henry/gitr/MAS/lib/MAS/Global.pm syntax OK

Perl itself can find it:

# perldoc -l MAS::Global /home/henry/gitr/MAS/lib/MAS/Global.pm

Compiler and OS details

# perl -v This is perl 5, version 38, subversion 2 (v5.38.2) built for x86_64-li +nux-gnu-thread-multi (with 51 registered patches, see perl -V for more detail) # cat /etc/os-release NAME="Linux Mint" VERSION="22.2 (Zara)" ID=linuxmint ID_LIKE="ubuntu debian" ... etc

I'm fairly sure there's a sensible explanation for this baffling behaviour: would someone either diagnose my error, or suggest some way by which I can home in on what it is?

Replies are listed 'Best First'.
Re: prove can't find my module, even though its directory is in $INC[0]
by choroba (Cardinal) on Dec 14, 2025 at 23:30 UTC
    It seems your test uses require with a string value, e.g.
    require 'MAS::Global'; # or my $class = 'MAS::Global'; require $class;

    That's not how require works. In fact, the documentation of the command tells you exactly that:

    If EXPR is a bareword, "require" assumes a .pm extension and replaces "::" with "/" in the filename for you, to make it easy to load standard modules. This form of loading of modules does not risk altering your namespace.
    In other words, if you try this:
    require Foo::Bar; # a splendid bareword
    The require function will actually look for the Foo/Bar.pm file in the directories specified in the @INC array.
    But if you try this:
    my $class = 'Foo::Bar'; require $class; # $class is not a bareword #or require "Foo::Bar"; # not a bareword because of +the ""
    The require function will look for the Foo::Bar file in the @INC array and will complain about not finding Foo::Bar there. In this case you can do:
    eval "require $class";

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      I will add that if they are doing that, it seems like they are trying to explicitly test that the module loads ok, but in a non-standard way.

      The old Test::More framework has a use_ok function, but it is a good idea to only use it in a test file that just does that one test, since other tests may be impacted negatively by not having the module loaded at compile time.

      The new Test2 removes use_ok and just recommends a regular use of the module in your test files.
      No, the test file t/8bit.t uses a simple use MAS::Global;. I just checked.

        You said you got this error message:

        Can't locate MAS::Global in @INC [...]

        The error message indicates that Perl is looking for a file named MAS::Global when you want it to look for a file named MAS/Global.pm.

        This happens, like choroba said, when require "MAS::Global"; is used instead of require MAS::Global; or require "MAS/Global.pm";.

        $ perl -e'require "MAS::Global";' # Bad Can't locate MAS::Global in @INC [...] at -e line 1. $ perl -e'require MAS::Global;' # Ok Can't locate MAS/Global.pm in @INC [...] at -e line 1. $ perl -e'require "MAS/Global.pm";' # Ok Can't locate MAS/Global.pm in @INC [...] at -e line 1.

        So check again, because require "MAS::Global"; or equivalent is definitely used somewhere in your code. The full error message will even say in what file and on what line. Add use Carp::Always; if you need a stack trace.

        If you're still unable to find the problem, start by providing the full (unedited) error message.


        In case you need it, the following is a portable method of converting a package name to a path for require:

        # Equivalent to what `if.pm` uses. my $require_path = $pkg_name =~ s{::}{/}gr . ".pm";
Re: prove can't find my module, even though its directory is in $INC[0]
by atcroft (Abbot) on Dec 15, 2025 at 08:22 UTC

    There are two things I might suggest:

    • perl -c ./t/8bit.t
    • prove -I/home/henry/gitr/MAS/lib ./t/8bit.t

    In the output you provided you gave perl -c /home/henry/gitr/MAS/lib/MAS/Global.pl as an example to show that perl could find it; however, that command would only check the syntax of the file name you provided (the full path to the module). By running perl -c ./t/8bit.t you have perl check the syntax of the test file (it's perl code too, after all), and if it can see the module it should pass.

    prove's -I option adds a library path for prove to include when running. prove's man page includes this comment about @INC:

    @INC
    prove introduces a separation between "options passed to the perl which runs prove" and "options passed to the perl which runs tests"; this distinction is by design. Thus the perl which is running a test starts with the default @INC. Additional library directories can be added via the "PERL5LIB" environment variable, via -Ifoo in "PERL5OPT" or via the "-Ilib" option to prove.
    It looks as if using the -I option might add the given path you need to have the test complete successfully.

    Hope that helps.

      My example showing how Perl could find the module was actually perldoc -l which correctly identified the source as /home/henry/gitr/MAS/lib. So Perl's own module-search routines are working OK.

      I tried the -I option, with the same baffling result:

      /usr/bin/prove -I/home/henry/gitr/MAS/lib ./t/8bit.t ./t/8bit.t .. Can't locate MAS::Global in @INC (@INC entries checked: +/home/henry/gitr/MAS/lib ... etc

      The section in the docs that you point out, that there's a separate set of options passed to "options passed to the perl which runs tests" is interesting; but use of the -I option, as it recommends, shows that that's not the problem either.

      I remain baffled, and stymied ...

        Out of curiosity, what does your 'package' statement in the module look like? Is it something like package MAS::Global; , or package Global;?

        I ask because I did a quick test of some code I was working on recently. My code was under ./lib/My/Particle/Moveable.pm, and my test ran correctly if I used package My::Particle::Moveable; but not if I did package Moveable;. (I remember there was some reason for doing it one way and not the other, but I can't remember it at the moment.)

        Hope that helps.

        > My example showing how Perl could find the module was actually perldoc -l which correctly identified the source as /home/henry/gitr/MAS/lib.

        Better don't count on that, AFAIR is perldoc using another mechanism to locate documentation.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

Re: prove can't find my module, even though its directory is in $INC[0]
by pfaut (Priest) on Dec 14, 2025 at 23:11 UTC

    Are you sure PERL5LIB is exported? Try 'env | grep PERL5LIB'. If it doesn't appear then you need to 'export PERL5LIB'.

    90% of every Perl application is already written.
    dragonchild
Re: prove can't find my module, even though its directory is in $INC[0]
by HenryLaw (Novice) on Dec 15, 2025 at 10:03 UTC
    Curiouser and curiouser. I cloned the project onto a different (virtual) machine, also running Mint 22.2 and prove for that test file works fine. So it's definitely something I have done, but I'm no closer to finding what.
Re: prove can't find my module, even though its directory is in $INC[0]
by ysth (Canon) on Dec 15, 2025 at 15:36 UTC
    Does prove --lib ... work?

      No; prove -l gives the same result (in fact that's what I usually enter, by force of habit).

      prove -l ./t/8bit.t reports that /home/henry/gitr/MAS/lib is in the path and then fails to find Global.pm, even though /home/henry/gitr/MAS/lib/MAS/Global.pm exists, and contains contains the line package MAS::Global;

        contains contains the line package MAS::Global;

        The package directive is irrelevant. That's not used to load a module. (It can be relevant to the later step of importing symbols when using use, but the error happens before that.)

        and then fails to find Global.pm

        Not quite. The issue isn't that perl can't find Global.pm (or rather, MAS/Global.pm); it's that it's not even looking for it. As previously explained, the message indicates it's looking for a file named MAS::Global (i.e. /home/henry/gitr/MAS/lib/MAS::Global). No such file exists, thus the failure.

        In the earlier post where I explained this, I requested that you start by providing the complete (unedited) error message (referring the output from prove ./t/8bit.t) if you were still having issues.

        Can you show 8bit.t? You said this doesn't happen in a different environment, are the repo files all the same when it doesn't happen?
Re: prove can't find my module, even though its directory is in $INC[0]
by HenryLaw (Novice) on Dec 15, 2025 at 19:09 UTC

    More curiosity: this problem seems to be confined to this particular project (in the git sense). If I switch to another project prove -l works as expected.

    I'll clone the project afresh from my git server and see if that makes any difference