The module isn't gone — it's just invisible. Ubuntu's Perl upgrades (5.34 on 22.04, 5.38 on 24.04, 5.40 after that) each search a different set of version-numbered directories listed in @INC, so anything you installed from CPAN under the old version's directory is never looked at again. The lasting fix is to install Perl modules from Ubuntu's own packages — here, sudo apt install libdatetime-format-strptime-perl — because apt keeps its modules matched to the installed interpreter across release upgrades. Treat CPAN as the fallback, not the default.
Why a Perl upgrade hides your modules
The @INC list in the error message belongs to one specific interpreter build. Ubuntu gives every major Perl version its own site directories: under Perl 5.38.2 that includes /usr/local/share/perl/5.38.2, and under 5.40 the equivalent directory carries the new number. When you install with cpan, the module is placed into the directory of the interpreter you ran it with — and nothing records that it should follow you to the next one.
That's why the old file still exists on disk yet the upgraded interpreter can't find it: no entry in the new @INC points there, and neither apt nor CPAN tooling migrates it. Modules from Ubuntu packages behave differently. Pure-Perl parts land in /usr/share/perl5, which is not version-numbered, while compiled parts go under a versioned architecture directory; each package declares the Perl API it requires, so a release upgrade automatically pulls in builds made for the new interpreter.
Confirm the diagnosis
Two quick checks make the picture unambiguous:
perl -V
find /usr/local/share/perl /usr/local/lib/perl -name 'Strptime.pm'
The first shows the running Perl version and the full search path; the second locates copies of the module on disk. If the file turns up only under an old version directory while perl -V reports a newer one, this is exactly the failure mode — the interpreter's search list and your installed files have drifted apart.
The durable fix: let apt manage your modules
Most popular CPAN distributions are packaged for Ubuntu. The naming convention is predictable: DateTime::Format::Strptime becomes libdatetime-format-strptime-perl — a lib prefix, lowercase with :: replaced by dashes, and -perl appended. To find packages for other modules:
sudo apt install apt-file && sudo apt-file update
apt-file search Strptime.pm
apt-cache search --names-only 'libdatetime-format-strptime'
Then install, enabling the universe repository first if it isn't active:
sudo add-apt-repository universe
sudo apt install libdatetime-format-strptime-perl
Because dpkg now owns the module, dependencies are resolved automatically, security updates arrive through the normal package channels, and the next release upgrade carries the module forward with the interpreter instead of stranding it.
When a module only exists on CPAN
Sometimes you genuinely need something the repositories lack. In that case, avoid scattering installs into version-locked directories. Install cpanminus from apt and give it a stable, version-independent home:
sudo apt install cpanminus
cpanm --local-lib /opt/perl-local DateTime::Format::Strptime
Add the resulting library path to ~/.profile:
export PERL5LIB="/opt/perl-local/lib/perl5${PERL5LIB:+:$PERL5LIB}"
This path contains no version number, so it stays on the search path across upgrades. One caveat: modules with compiled C components are built for a specific interpreter, so after a major Perl upgrade they must be rebuilt even though the directory is unchanged. Keep a cpanfile listing what you depend on so the rebuild is one scripted command:
# cpanfile
requires 'DateTime::Format::Strptime';
# after an interpreter upgrade:
cpanm --local-lib /opt/perl-local --installdeps .
As a one-off stopgap, PERL5LIB=/usr/local/share/perl/5.34.0 perl script.pl can unblock a broken script immediately — but only for pure-Perl code. Binary extensions compiled for the old interpreter can crash the new one, so don't make a habit of it.
Habits that prevent a repeat
- Default to apt for Perl modules; reach for CPAN only when a module is missing from the repositories or you need a feature from a newer version.
- After any release upgrade, run
ls /usr/local/share/perl/— more than one version directory means CPAN-installed modules were stranded and need reinstalling. - Keep a manifest (
cpanfileor a plain list) of every CPAN module you rely on, so recovery is scripted rather than improvised. - For scripts you deploy elsewhere, vendor dependencies next to the script with
cpanm -L local ...so they travel with the code, not the OS.
Frequently Asked Questions
Why can't Perl just keep searching the old directories?
Version separation is deliberate: binary modules are compiled against one interpreter and can misbehave under another. Keeping each build's site libraries separate prevents an upgrade from silently mixing incompatible code.
Is symlinking the old version directory to the new one safe?
It often works for pure-Perl modules, but any compiled extension in that tree was built for the previous interpreter and can crash the current one. Reinstalling — or better, installing the apt package — is the reliable route.
How do I tell which modules came from apt and which from CPAN?
Anything under /usr/local was installed outside the package manager. For a specific file, run dpkg -S /path/to/Module.pm: if dpkg owns it, upgrades will maintain it; if not, it's yours to track.
The cpan command printed thousands of lines. Is that normal?
Yes. CPAN builds each module and its dependency chain from source, which is slow and noisy. The matching apt package installs prebuilt binaries with dependencies resolved in seconds.
What should I do right now if a script is broken?
Check for an apt package for the missing module and install it — that's the permanent fix. If none exists, reinstall via cpanm into a stable local directory, or temporarily set PERL5LIB to the old version directory as a stopgap.