python/cpython · error · TypeError
cannot pickle {self.__class__.__name__!r} object
Error message
cannot pickle {self.__class__.__name__!r} object What it means
IOBase.__getstate__ (Lib/_pyio.py:851) deliberately raises TypeError to make file objects unpicklable: open streams wrap OS descriptors, sockets, or memory state that cannot be serialized meaningfully. Any pickling path (pickle.dumps, copy.deepcopy, multiprocessing transfer, functools.cache-style caching) hits this.
Source
Thrown at Lib/_pyio.py:851
@property
def raw(self):
return self._raw
@property
def closed(self):
return self.raw.closed
@property
def name(self):
return self.raw.name
@property
def mode(self):
return self.raw.mode
def __getstate__(self):
raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")
def __repr__(self):
modname = self.__class__.__module__
clsname = self.__class__.__qualname__
try:
name = self.name
except AttributeError:
return "<{}.{}>".format(modname, clsname)
else:
return "<{}.{} name={!r}>".format(modname, clsname, name)
def _dealloc_warn(self, source):
if dealloc_warn := getattr(self.raw, "_dealloc_warn", None):
dealloc_warn(source)
### Lower-level APIs ###
def fileno(self):View on GitHub (pinned to bc6749cc3b)
Solutions
- Pickling the contents instead of the handle: read first, then pickle `f.read()` bytes or the parsed data.
- In multiprocessing, pass file paths (or file descriptors via multiprocessing.reduction) rather than file objects.
- For deep structures, implement __getstate__ on your own class that excludes file fields and reopens in __setstate__.
- As a last resort, use a library that supports pickling handles (dill/cloudpickle), understanding the target process must be able to use the descriptor.
Example fix
# before
f = open('model.bin', 'rb')
pickle.dumps(f) # TypeError: cannot pickle 'BufferedReader' object
# after
with open('model.bin', 'rb') as f:
blob = f.read()
pickle.dumps(blob) Defensive patterns
Strategy: type-guard
Validate before calling
def pickle_payload(obj):
import pickle
for attr, val in vars(obj).items():
if isinstance(val, io.IOBase):
raise TypeError(f'{attr} is an open stream; extract data before pickling')
return pickle.dumps(obj) Type guard
def is_unpicklable_stream(v) -> bool:
return isinstance(v, (io.IOBase, io.BufferedIOBase, io.TextIOBase)) Try / catch
try:
blob = pickle.dumps(obj)
except TypeError as e:
if 'cannot pickle' in str(e):
raise TypeError('strip file handles before serializing') from e
raise Prevention
- Never store open file objects in objects destined for pickle/multiprocessing queues.
- Pass paths or bytes, not handles, across process boundaries.
- Add a __getstate__ to your own classes that drops file fields and reopens lazily in __setstate__.
When it happens
Trigger: pickle.dumps(open_file); passing an open file or buffered reader as an argument to multiprocessing.Process or a Pool; copy.deepcopy(f); putting file objects in objects sent over a queue.
Common situations: Sending a config object to worker processes where one field accidentally holds an open file; deepcopy of request contexts that captured an upload stream; caching functions that pickle their results/inputs.
Related errors
- Failed to encode latin1 string when unpickling a date object
- bad tzinfo state arg
- invalid file: %r
- invalid mode: %r
- invalid buffering: %r
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/77a1c9d427b7546c.
Report an issue: GitHub.