 <p>The class defining <a href="https://docs.python.org/2/reference/datamodel.html#__slots__" rel="nofollow noreferrer"><code>__slots__</code></a> (and not <a href="https://docs.python.org/2/library/pickle.html#object.__getstate__" rel="nofollow noreferrer"><code>__getstate__</code></a>) can be either an ancestor class of yours, or a class (or ancestor class) of an attribute or item of yours, directly or indirectly: essentially, the class of any object in the <em>directed graph</em> of references with your object as root, since pickling needs to save the entire graph.</p> <p>A simple solution to your quandary is to use protocol <code>-1</code>, which means "the best protocol pickle can use"; the default is an ancient ASCII-based protocol which imposes this limitation about <code>__slots__</code> vs <code>__getstate__</code>. Consider:</p> <pre><code>&gt;&gt;&gt; class sic(object): ... __slots__ = 'a', 'b' ... &gt;&gt;&gt; import pickle &gt;&gt;&gt; pickle.dumps(sic(), -1) '\x80\x02c__main__\nsic\nq\x00)\x81q\x01.' &gt;&gt;&gt; pickle.dumps(sic()) Traceback (most recent call last): [snip snip] raise TypeError("a class that defines __slots__ without " TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled &gt;&gt;&gt; </code></pre> <p>As you see, protocol <code>-1</code> takes the <code>__slots__</code> in stride, while the default protocol gives the same exception you saw.</p> <p>The issues with protocol <code>-1</code>: it produces a binary string/file, rather than an ASCII one like the default protocol; the resulting pickled file would not be loadable by sufficiently ancient versions of Python. Advantages, besides the key one wrt <code>__slots__</code>, include more compact results, and better performance.</p> <p>If you're forced to use the default protocol, then you'll need to identify exactly which class is giving you trouble and exactly why. We can discuss strategies if this is the case (but if you can possibly use the <code>-1</code> protocol, that's so much better that it's not worth discussing;-) and simple code inspection looking for the troublesome class/object is proving too complicated (I have in mind some deepcopy-based tricks to get a usable representation of the whole graph, in case you're wondering).</p>