# Buggy code
def rescandirs(
    self,
    shared,
    oldmtimes,
    oldfiles,
    sharedfilesstreams,
    yieldfunction,
    progress=None,
    name="",
    rebuild=False,
):
    """
    Check for modified or new files via OS's last mtime on a directory,
    or, if rebuild is True, all directories
    """

    # returns dict in format:  { Directory : mtime, ... }
    shared_directories = [x[1] for x in shared]

    GLib.idle_add(progress.set_text, _("Checking for changes"))
    GLib.idle_add(progress.show)
    GLib.idle_add(progress.set_fraction, 0)

    self.logMessage(
        _("%(num)s directories found before rescan, rebuilding...")
        % {"num": len(oldmtimes)}
    )

    newmtimes = self.getDirsMtimes(shared_directories, yieldfunction)

    GLib.idle_add(progress.set_text, _("Scanning %s") % name)

    # Get list of files
    # returns dict in format { Directory : { File : metadata, ... }, ... }
    newsharedfiles = self.getFilesList(
        newmtimes, oldmtimes, oldfiles, yieldfunction, progress, rebuild
    )

    # Pack shares data
    # returns dict in format { Directory : hex string of files+metadata, ... }
    GLib.idle_add(progress.set_text, _("Building Database"))

    newsharedfilesstreams = self.getFilesStreams(
        newmtimes, oldmtimes, sharedfilesstreams, newsharedfiles, rebuild, yieldfunction
    )

    # Update Search Index
    # newwordindex is a dict in format {word: [num, num, ..], ... } with num matching
    # keys in newfileindex
    # newfileindex is a dict in format { num: (path, size, (bitrate, vbr), length), ... }
    GLib.idle_add(progress.set_text, _("Building Index"))

    GLib.idle_add(progress.set_fraction, 0.0)

    newwordindex, newfileindex = self.getFilesIndex(
        newmtimes,
        oldmtimes,
        shared_directories,
        newsharedfiles,
        yieldfunction,
        progress,
    )

    GLib.idle_add(progress.set_fraction, 1.0)

    self.logMessage(
        _("%(num)s directories found after rescan") % {"num": len(newmtimes)}
    )

    return newsharedfiles, newsharedfilesstreams, newwordindex, newfileindex, newmtimes


# Traceback (KeyError)
Traceback (most recent call last):
File "/usr/local/lib/python3.7/shelve.py", line 111, in __getitem__
value = self.cache[key]
KeyError: 'Klassiek\\Jean Sibelius\\Two Serenades for Violin and Orchestra, Op.69'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/pynicotine/gtkgui/frame.py", line 2039, in _RescanFinished
self.np.shares.sendNumSharedFoldersFiles()
File "/usr/local/lib/python3.7/site-packages/pynicotine/shares.py", line 105, in sendNumSharedFoldersFiles
sharedfiles = sum([len(x) for x in list(conf["transfers"][shared_db].values())])
File "/usr/local/lib/python3.7/_collections_abc.py", line 762, in __iter__
yield self._mapping[key]
File "/usr/local/lib/python3.7/shelve.py", line 113, in __getitem__
f = BytesIO(self.dict[key.encode(self.keyencoding)])
File "/usr/local/lib/python3.7/shelve.py", line 70, in closed
raise ValueError('invalid operation on closed shelf')
ValueError: invalid operation on closed shelf

# Fixed code
def rescandirs(
    self,
    shared,
    oldmtimes,
    oldfiles,
    sharedfilesstreams,
    yieldfunction,
    progress=None,
    name="",
    rebuild=False,
):
    """
    Check for modified or new files via OS's last mtime on a directory,
    or, if rebuild is True, all directories
    """

    GLib.idle_add(progress.set_fraction, 0.0)
    GLib.idle_add(progress.show)

    # returns dict in format:  { Directory : mtime, ... }
    shared_directories = [x[1] for x in shared]

    self.logMessage(
        _("%(num)s directories found before rescan, rebuilding...")
        % {"num": len(oldmtimes)}
    )

    newmtimes = self.getDirsMtimes(shared_directories, yieldfunction)

    # Get list of files
    # returns dict in format { Directory : { File : metadata, ... }, ... }
    newsharedfiles = self.getFilesList(
        newmtimes, oldmtimes, oldfiles, yieldfunction, progress, rebuild
    )

    # Pack shares data
    # returns dict in format { Directory : hex string of files+metadata, ... }
    newsharedfilesstreams = self.getFilesStreams(
        newmtimes, oldmtimes, sharedfilesstreams, newsharedfiles, rebuild, yieldfunction
    )

    # Update Search Index
    # newwordindex is a dict in format {word: [num, num, ..], ... } with num matching
    # keys in newfileindex
    # newfileindex is a dict in format { num: (path, size, (bitrate, vbr), length), ... }
    newwordindex, newfileindex = self.getFilesIndex(
        newmtimes, oldmtimes, newsharedfiles, yieldfunction, progress
    )

    self.logMessage(
        _("%(num)s directories found after rescan") % {"num": len(newmtimes)}
    )

    return newsharedfiles, newsharedfilesstreams, newwordindex, newfileindex, newmtimes