python/cpython · error · ValueError
Failed to encode latin1 string when unpickling a datetime ob
Error message
Failed to encode latin1 string when unpickling a datetime object. pickle.load(data, encoding='latin1') is assumed.
What it means
Raised by datetime.__new__ during unpickling when the 10-character str payload cannot be encoded to latin1. Datetimes are pickled as a compact byte string; loading such a pickle with a non-latin1 encoding (e.g. encoding='utf-8') can yield a str with characters above U+00FF, and reconstruction aborts with this ValueError telling you the assumed encoding.
Source
Thrown at Lib/_pydatetime.py:1800
class datetime(date):
"""A combination of a date and a time.
The year, month and day arguments are required. tzinfo may be None, or an
instance of a tzinfo subclass. The remaining arguments may be ints.
"""
__slots__ = time.__slots__
def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
microsecond=0, tzinfo=None, *, fold=0):
if (isinstance(year, (bytes, str)) and len(year) == 10 and
1 <= ord(year[2:3])&0x7F <= 12):
# Pickle support
if isinstance(year, str):
try:
year = bytes(year, 'latin1')
except UnicodeEncodeError:
# More informative error message.
raise ValueError(
"Failed to encode latin1 string when unpickling "
"a datetime object. "
"pickle.load(data, encoding='latin1') is assumed.")
self = object.__new__(cls)
self.__setstate(year, month)
self._hashcode = -1
return self
year, month, day = _check_date_fields(year, month, day)
hour, minute, second, microsecond, fold = _check_time_fields(
hour, minute, second, microsecond, fold)
_check_tzinfo_arg(tzinfo)
self = object.__new__(cls)
self._year = year
self._month = month
self._day = day
self._hour = hour
self._minute = minute
self._second = secondView on GitHub (pinned to bc6749cc3b)
Solutions
- Load with encoding='latin1': pickle.load(f, encoding='latin1')
- Re-pickle everything in Python 3 (protocol 4+) or migrate storage to ISO-format JSON
- Write a one-time conversion script that loads with latin1 and re-dumps safely
Example fix
# before obj = pickle.load(f, encoding='utf-8') # after obj = pickle.load(f, encoding='latin1')
Defensive patterns
Strategy: try-catch
Validate before calling
if isinstance(v, str) and len(v) == 10 and any(ord(c) > 255 for c in v[:3]):
raise ValueError('non-latin1 datetime payload; use encoding=latin1') Try / catch
try:
obj = pickle.load(f, encoding='latin1')
except ValueError:
# not a latin1-encoded pickle after all; surface clearly
raise Prevention
- Load legacy pickles with encoding='latin1' per the stdlib contract
- Migrate pickled archives to protocol >= 4 or JSON once, then drop the legacy path
- Version your persisted payloads so decode strategy is explicit
When it happens
Trigger: pickle.load(f, encoding='utf-8') on a pickle containing a datetime.datetime; Python 2 pickles of datetimes loaded into Python 3 with the wrong encoding argument; pickle tools/streams that decode payload strings to utf-8 by default.
Common situations: Python 2 -> 3 data migrations of pickled records; cached pickles in files/Redis/DBs written by old interpreters; generic unpickle helpers defaulting encoding to 'utf-8'.
Related errors
- Failed to encode latin1 string when unpickling a time object
- Failed to encode latin1 string when unpickling a date object
- Unknown timespec value
- Invalid ISO string
- Invalid isoformat string
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/304c1250d1d0c1b0.
Report an issue: GitHub.