Search code examples
perltiestorable

Error restoring from nstore_fd: Can't locate object method "FIRSTKEY" via package "Hash::Case::Lower"


I am doing some archeology of a program from 2005. It's been happily writing backups like this:

use Storable qw(nstore_fd);  
my %data = 
    (
     "Games" => \%Games,
     "Members" => \%Members,
     "Scenarios" => \%Scenarios,
     "Passwords" => \%Passwords,
     "TourneyNames" => \%TourneyNames
     );

    nstore_fd(\%data, *BACKUP) or die "Can't write backup: $!";

I need to recover some of this data.

I did this:

use Storable qw(fd_retrieve); 

$data = fd_retrieve(*STDIN);  # the backup file 

print keys %{$data}, "\n";

foreach $thing (keys(%{$data})) {
    print "$thing\n";
    print scalar keys %{$data->{$thing}}, "\n";
}

and got:

$ perl ~/foo.pl < BobsterBackup2018-7-9-35131.bak
GamesMembersPasswordsScenariosTourneyNames
Games
15556
Members
Can't locate object method "FIRSTKEY" via package "Hash::Case::Lower" at /Users/mgregory/foo.pl line 9.
$ 

I see that the original source has:

tie %Members, 'Hash::Case::Lower';    # index by non-case-sensitive member-name.

... but I'm at a loss what to make of it!


Solution

  • When you restore objects that are tied to packages, you first need to load their classes. Storable as well as, for example, Sereal will not load them for you. It recreates the objects as they are stored, and Perl expects the packages to exist.

    All you need to do is load the module before deserializing your backup.

    use Storable qw(fd_retrieve); 
    use Hash::Case::Lower;
    
    my $data = fd_retrieve(*STDIN);  # the backup file