# Buggy code
def on_task_modify(self, task, config):
    # Only scan through accepted entries, as the file must have been downloaded in order to parse anything
    for entry in task.accepted:
        # skip if entry does not have file assigned
        if "file" not in entry:
            log.trace("%s doesn't have a file associated", entry["title"])
            continue
        if not os.path.exists(entry["file"]):
            log.debug("File %s does not exist", entry["file"])
            continue
        if os.path.getsize(entry["file"]) == 0:
            log.debug("File %s is 0 bytes in size", entry["file"])
            continue
        if not is_torrent_file(entry["file"]):
            continue
        log.debug("%s seems to be a torrent", entry["title"])

        # create torrent object from torrent
        try:
            with open(entry["file"], "rb") as f:
                # NOTE: this reads entire file into memory, but we're pretty sure it's
                # a small torrent file since it starts with TORRENT_RE
                data = f.read()

            if "content-length" in entry:
                if len(data) != entry["content-length"]:
                    entry.fail(
                        "Torrent file length doesn't match to the one reported by the server"
                    )
                    self.purge(entry)
                    continue

            # construct torrent object
            try:
                torrent = Torrent(data)
            except SyntaxError as e:
                entry.fail("%s - broken or invalid torrent file received" % e.args[0])
                self.purge(entry)
                continue

            entry["torrent"] = torrent
            entry["torrent_info_hash"] = torrent.info_hash
            # if we do not have good filename (by download plugin)
            # for this entry, try to generate one from torrent content
            if entry.get("filename"):
                if not entry["filename"].lower().endswith(".torrent"):
                    # filename present but without .torrent extension, add it
                    entry["filename"] += ".torrent"
            else:
                # generate filename from torrent or fall back to title plus extension
                entry["filename"] = self.make_filename(torrent, entry)
        except Exception as e:
            log.exception(e)


# Traceback (AttributeError)
2017-11-12 19:46 DEBUG    modif_torrent download-series-discover The.series.name.S02E06.REAL.HDTV.x264-SVA[rartv] seems to be a torrent
2017-11-12 19:46 DEBUG    entry         download-series-discover trying to debug key `torrent` value threw exception: 'str' object has no attribute 'get'
2017-11-12 19:46 ERROR    modif_torrent download-series-discover 'str' object has no attribute 'items'
Traceback (most recent call last):
File "/home/osmc/flexget/lib/python3.4/site-packages/flexget/plugins/modify/torrent.py", line 61, in on_task_modify
entry['torrent_info_hash'] = torrent.info_hash
File "/home/osmc/flexget/lib/python3.4/site-packages/flexget/utils/bittorrent.py", line 297, in info_hash
info_data = encode_dictionary(self.content['info'])
File "/home/osmc/flexget/lib/python3.4/site-packages/flexget/utils/bittorrent.py", line 170, in encode_dictionary
items = list(data.items())
AttributeError: 'str' object has no attribute 'items'

# Fixed code
def on_task_modify(self, task, config):
    # Only scan through accepted entries, as the file must have been downloaded in order to parse anything
    for entry in task.accepted:
        # skip if entry does not have file assigned
        if "file" not in entry:
            log.trace("%s doesn't have a file associated", entry["title"])
            continue
        if not os.path.exists(entry["file"]):
            log.debug("File %s does not exist", entry["file"])
            continue
        if os.path.getsize(entry["file"]) == 0:
            log.debug("File %s is 0 bytes in size", entry["file"])
            continue
        if not is_torrent_file(entry["file"]):
            continue
        log.debug("%s seems to be a torrent", entry["title"])

        # create torrent object from torrent
        try:
            with open(entry["file"], "rb") as f:
                # NOTE: this reads entire file into memory, but we're pretty sure it's
                # a small torrent file since it starts with TORRENT_RE
                data = f.read()

            if "content-length" in entry:
                if len(data) != entry["content-length"]:
                    entry.fail(
                        "Torrent file length doesn't match to the one reported by the server"
                    )
                    self.purge(entry)
                    continue

            # construct torrent object
            try:
                torrent = Torrent(data)
            except SyntaxError as e:
                entry.fail("%s - broken or invalid torrent file received" % e.args[0])
                self.purge(entry)
                continue

            log.trace("working on torrent %s", torrent)
            entry["torrent"] = torrent
            entry["torrent_info_hash"] = torrent.info_hash
            # if we do not have good filename (by download plugin)
            # for this entry, try to generate one from torrent content
            if entry.get("filename"):
                if not entry["filename"].lower().endswith(".torrent"):
                    # filename present but without .torrent extension, add it
                    entry["filename"] += ".torrent"
            else:
                # generate filename from torrent or fall back to title plus extension
                entry["filename"] = self.make_filename(torrent, entry)
        except Exception as e:
            log.exception(e)