{"record":{"id":"5b0fdd5bf1c29e12","repo":"stamparm/maltrail","slug":"unsupported-type-s","errorCode":null,"errorMessage":"unsupported type '%s'","messagePattern":"unsupported type '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/trailsdict.py","lineNumber":272,"sourceCode":"                return pair_list[values[i]]\n            i += 1\n        return default\n\n    def __len__(self):\n        mm = self._mmap\n        if mm is not None:\n            return mm[\"length\"]\n        frozen = self._frozen\n        return frozen[5] if frozen is not None else len(self._trails)\n\n    def clear(self):\n        self.__init__()\n\n    def __setitem__(self, key, value):\n        if self._frozen is not None or self._mmap is not None:\n            raise Exception(\"cannot modify a finalized TrailsDict\")\n        if not isinstance(value, (tuple, list)):\n            raise Exception(\"unsupported type '%s'\" % type(value))\n\n        pair = (value[0], value[1])\n        shared = self._pairs.get(pair)\n        if shared is None:\n            shared = pair\n            self._pairs[pair] = pair\n        self._trails[key] = shared\n\n    def __delitem__(self, key):\n        if self._frozen is not None or self._mmap is not None:\n            raise Exception(\"cannot modify a finalized TrailsDict\")\n        del self._trails[key]\n\n    def update(self, value):\n        if self._frozen is not None or self._mmap is not None:\n            raise Exception(\"cannot modify a finalized TrailsDict\")\n        if isinstance(value, (TrailsDict, dict)):\n            for key in value:","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/core/trailsdict.py#L254-L290","documentation":"Validation guard in TrailsDict.__setitem__: the value assigned to a key must be a tuple or list (a trail of hop pairs); any other type — a plain string, int, dict, None, etc. — is rejected. This is a sentinel-style generic Exception used to enforce the container's value contract before the value is normalized into the internal pair/value storage. Fix by passing the trail as a tuple/list of pairs, e.g. td[key] = (('1.2.3.4', '5.6.7.8'), ...), or by wrapping scalars in the structure the API expects.","triggerScenarios":"trails[key] = \"some string\"; assigning None, an int, or a dict; passing a generator/iterator instead of a materialized pair; refactoring changed value shape from tuple to custom object.","commonSituations":"Typos or refactors in update scripts, JSON/CSV loaders yielding strings, code adapted from a different trails structure.","solutions":["Wrap the value in a tuple, e.g. trails[key] = (interval, \"malware\")","Ensure loaders convert each row to a tuple/list before assignment","Add an isinstance check on values before writing","Catch Exception in the update loop and log the offending type"],"exampleFix":"// before\ntrails[key] = value  # value is a str from CSV\n// after\ninterval, name = value.split(\",\")\ntrails[key] = (int(interval), name)","handlingStrategy":"type-guard","validationCode":"def trails_value_ok(value):\n    return isinstance(value, (tuple, list)) and len(value) >= 2","typeGuard":"def is_trail_pair(value):\n    return isinstance(value, (tuple, list)) and len(value) >= 2","tryCatchPattern":"try:\n    trails[key] = value\nexcept Exception as e:\n    if \"unsupported type\" in str(e):\n        trails[key] = tuple(value) if isinstance(value, (list, tuple)) else (value, \"\")","preventionTips":["Always assign 2-element (interval, type) tuples","Coerce loader output (CSV/JSON strings) into tuples before assignment","Add a helper setter that validates the pair shape","Cover value-type contract in unit tests"],"tags":["python","type-check","dict"],"backgroundTag":"type-mismatch","analyzedSha":"77cfb06d7606506d101bbcec0786c77166c4255e","analyzedAt":"2026-09-13T03:50:16.010Z","contentChangedAt":"2026-09-13T03:50:16.010Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}