{"record":{"id":"680d5c3272457a26","repo":"pypa/pip","slug":"cannot-serialize-obj-r-where-tzinfo-none","errorCode":null,"errorMessage":"Cannot serialize {obj!r} where tzinfo=None","messagePattern":"Cannot serialize (.+?) where tzinfo=None","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/msgpack/fallback.py","lineNumber":802,"sourceCode":"                self._pack_array_header(n)\n                for i in range(n):\n                    self._pack(obj[i], nest_limit - 1)\n                return\n            if check(obj, dict):\n                return self._pack_map_pairs(len(obj), obj.items(), nest_limit - 1)\n\n            if self._datetime and check(obj, _DateTime) and obj.tzinfo is not None:\n                obj = Timestamp.from_datetime(obj)\n                default_used = 1\n                continue\n\n            if not default_used and self._default is not None:\n                obj = self._default(obj)\n                default_used = 1\n                continue\n\n            if self._datetime and check(obj, _DateTime):\n                raise ValueError(f\"Cannot serialize {obj!r} where tzinfo=None\")\n\n            raise TypeError(f\"Cannot serialize {obj!r}\")\n\n    def pack(self, obj):\n        try:\n            self._pack(obj)\n        except:\n            self._buffer = BytesIO()  # force reset\n            raise\n        if self._autoreset:\n            ret = self._buffer.getvalue()\n            self._buffer = BytesIO()\n            return ret\n\n    def pack_map_pairs(self, pairs):\n        self._pack_map_pairs(len(pairs), pairs)\n        if self._autoreset:\n            ret = self._buffer.getvalue()","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/msgpack/fallback.py#L784-L820","documentation":"Raised by msgpack's pure-Python Packer._pack when datetime support is enabled (datetime=True, the default in newer versions) but the datetime object has tzinfo=None — a naive datetime. The Timestamp extension type computes UTC seconds from dt.timestamp(), which for naive datetimes is ambiguous (interpreted as local time), so msgpack explicitly refuses to serialize it to prevent silent data corruption.","triggerScenarios":"Packing a datetime.datetime or datetime.time without tzinfo set while the Packer is configured with datetime=True (or the default enables it). The code path at line 791 checks obj.tzinfo is not None before converting; line 802 catches the fallback where tzinfo is still None.","commonSituations":"Application creates datetime.now() (naive, local) instead of datetime.now(timezone.utc); data from a database or CSV parsed as naive datetimes; legacy code predating timezone-aware datetimes.","solutions":["Make the datetime timezone-aware before packing: dt.replace(tzinfo=timezone.utc) or dt.astimezone(timezone.utc).","Use datetime.now(timezone.utc) instead of datetime.now() at creation time.","If the original timezone is unknown but you know it is UTC, attach tzinfo=datetime.timezone.utc explicitly.","Disable datetime support (datetime=False) and serialize the datetime yourself if you must handle naive datetimes."],"exampleFix":"# before\nimport datetime\npacker = msgpack.Packer(datetime=True)\npacker.pack(datetime.datetime(2024, 1, 1))  # naive — raises\n\n# after\ndt = datetime.datetime(2024, 1, 1, tzinfo=datetime.timezone.utc)\npacker.pack(dt)","handlingStrategy":"validation","validationCode":"import datetime\n\ndef is_aware_datetime(dt) -> bool:\n    return isinstance(dt, datetime.datetime) and dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None","typeGuard":"import datetime\n\ndef is_timezone_aware(dt) -> bool:\n    return isinstance(dt, datetime.datetime) and dt.tzinfo is not None","tryCatchPattern":"import datetime\nfor dt in datetimes:\n    if dt.tzinfo is None:\n        dt = dt.replace(tzinfo=datetime.timezone.utc)\n    packer.pack(dt)","preventionTips":["Always use datetime.now(timezone.utc) instead of datetime.now().","Apply .replace(tzinfo=timezone.utc) to naive datetimes from external sources.","Use pydantic or attrs validators to enforce timezone-awareness.","Set a global lint rule or pre-commit check to flag naive datetime usage."],"tags":["msgpack","datetime","timezone","serialization"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}