{"record":{"id":"b4f882baefda8c7d","repo":"python/cpython","slug":"s-s-not-supported","errorCode":null,"errorMessage":"%s.%s() not supported","messagePattern":"(.+?)\\.(.+?)\\(\\) not supported","errorType":"exception","errorClass":"UnsupportedOperation","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":343,"sourceCode":"    Note that calling any method (even inquiries) on a closed stream is\n    undefined. Implementations may raise OSError in this case.\n\n    IOBase (and its subclasses) support the iterator protocol, meaning\n    that an IOBase object can be iterated over yielding the lines in a\n    stream.\n\n    IOBase also supports the :keyword:`with` statement. In this example,\n    fp is closed after the suite of the with statement is complete:\n\n    with open('spam.txt', 'r') as fp:\n        fp.write('Spam and eggs!')\n    \"\"\"\n\n    ### Internal ###\n\n    def _unsupported(self, name):\n        \"\"\"Internal: raise an OSError exception for unsupported operations.\"\"\"\n        raise UnsupportedOperation(\"%s.%s() not supported\" %\n                                   (self.__class__.__name__, name))\n\n    ### Positioning ###\n\n    def seek(self, pos, whence=0):\n        \"\"\"Change stream position.\n\n        Change the stream position to byte offset pos. Argument pos is\n        interpreted relative to the position indicated by whence.  Values\n        for whence are ints:\n\n        * 0 -- start of stream (the default); offset should be zero or\n          positive\n        * 1 -- current stream position; offset may be negative\n        * 2 -- end of stream; offset is usually negative\n        Some operating systems / file systems could provide additional\n        values.\n","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L325-L361","documentation":"Raised by IOBase._unsupported() as io.UnsupportedOperation (a subclass of both OSError and ValueError) when a stream method is called that the concrete stream class deliberately does not implement. Base/raw classes stub out methods like read, write, truncate, fileno with this generic '%s.%s() not supported' message naming the class and method.","triggerScenarios":"io.RawIOBase().read(10); calling .truncate() on a socket wrapper that did not override it; .fileno() on classes like io.BytesIO subclasses that inherit the unsupported stub; calling .write() on a read-only custom raw stream that never overrode write(). Also subprocess/pipe-based streams missing seek.","commonSituations":"Writing custom IOBase subclasses and forgetting to override the operations you advertise; generic framework code that probes capabilities by calling methods (instead of checking seekable()/readable()/writable()); mixing stream types (passing a raw stream where buffered/text expected).","solutions":["Check capabilities first: stream.seekable(), stream.readable(), stream.writable() (or hasattr) before invoking optional operations.","If you own the subclass, implement the missing method (or inherit from a richer base: io.RawIOBase instead of io.IOBase).","Catch io.UnsupportedOperation (note it is both OSError and ValueError) at the boundary where stream types vary.","Pass appropriately-wrapped streams (e.g. BufferedReader over a raw object) rather than raw stubs."],"exampleFix":"// before\ndata = stream.read(4096)   # UnsupportedOperation: RawIOBase-like stub\n\n// after\nif stream.readable():\n    data = stream.read(4096)\nelse:\n    data = None","handlingStrategy":"type-guard","validationCode":"ops = {'read': getattr(stream, 'readable', None),\n       'write': getattr(stream, 'writable', None),\n       'seek': getattr(stream, 'seekable', None)}\nfor name, probe in ops.items():\n    if probe and probe():\n        pass  # capability available; safe to call the corresponding method","typeGuard":"def supports(stream, op: str) -> bool:\n    probe = {'read': 'readable', 'write': 'writable', 'seek': 'seekable'}[op]\n    fn = getattr(stream, probe, None)\n    return callable(fn) and fn()","tryCatchPattern":"import io\n\ntry:\n    stream.truncate()\nexcept io.UnsupportedOperation:\n    pass  # this stream class does not implement truncate()","preventionTips":["Probe with readable()/writable()/seekable() instead of calling and catching.","When subclassing IOBase, override every operation your API contract promises.","Prefer composing io.BufferedReader/Writer over raw stubs when passing streams to stdlib consumers."],"tags":["io","stream","unsupported-operation","oserror","subclassing"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}