{"record":{"id":"56a523647e45f25e","repo":"python/cpython","slug":"must-have-exactly-one-of-create-read-write-append","errorCode":null,"errorMessage":"Must have exactly one of create/read/write/append mode and at most one plus","messagePattern":"Must have exactly one of create/read/write/append mode and at most one plus","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":1564,"sourceCode":"            raise TypeError('integer argument expected, got float')\n        if isinstance(file, int):\n            if isinstance(file, bool):\n                import warnings\n                warnings.warn(\"bool is used as a file descriptor\",\n                              RuntimeWarning, stacklevel=2)\n                file = int(file)\n            fd = file\n            if fd < 0:\n                raise ValueError('negative file descriptor')\n        else:\n            fd = -1\n\n        if not isinstance(mode, str):\n            raise TypeError('invalid mode: %s' % (mode,))\n        if not set(mode) <= set('xrwab+'):\n            raise ValueError('invalid mode: %s' % (mode,))\n        if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1:\n            raise ValueError('Must have exactly one of create/read/write/append '\n                             'mode and at most one plus')\n\n        if 'x' in mode:\n            self._created = True\n            self._writable = True\n            flags = os.O_EXCL | os.O_CREAT\n        elif 'r' in mode:\n            self._readable = True\n            flags = 0\n        elif 'w' in mode:\n            self._writable = True\n            self._truncate = True\n            flags = os.O_CREAT | os.O_TRUNC\n        elif 'a' in mode:\n            self._writable = True\n            self._appending = True\n            flags = os.O_APPEND | os.O_CREAT\n","sourceCodeStart":1546,"sourceCodeEnd":1582,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L1546-L1582","documentation":"Raised by FileIO.__init__ when mode does not contain exactly one of the create/read/write/append characters ('r','w','a','x') or contains more than one '+'. After charset validation, the constructor requires sum(c in 'rwax' for c in mode) == 1 and mode.count('+') <= 1, so combined modes like 'rw', 'wr+', or 'r++' are rejected.","triggerScenarios":"io.FileIO(path, 'rw') or io.FileIO(path, 'w+rb') — any mode with two of r/w/a/x, or with '++'; also 'rb+'. typo'd '+' duplication like 'r++'.","commonSituations":"Developers assuming 'rw' works like C's fopen extensions or other languages; building modes by concatenation (base + '+' + extra) where the base already contained a mode letter; refactoring 'r+b' into 'rb+' incorrectly.","solutions":["Use exactly one base mode: 'r' to read, 'w' to truncate/write, 'a' to append, 'x' to create-exclusively; add '+' only once (e.g. 'r+b') for read-write","Build modes from a validated choice, not string concatenation: mode in ('rb','wb','ab','xb','r+b','w+b','a+b','x+b')","If you need read-write on an existing file, use 'r+b'"],"exampleFix":"# before\nf = io.FileIO(path, 'rw')  # ValueError: Must have exactly one of create/read/write/append...\n\n# after\nf = io.FileIO(path, 'r+b')  # read-write, no truncate","handlingStrategy":"validation","validationCode":"import re\nif not re.fullmatch(r'[rwax][b+]{0,2}', mode):\n    raise ValueError(f'bad FileIO mode {mode!r}: need exactly one of r/w/a/x and at most one +')\nf = io.FileIO(path, mode)","typeGuard":"def is_valid_fileio_mode(m):\n    return (isinstance(m, str) and sum(c in 'rwax' for c in m) == 1\n            and m.count('+') <= 1 and set(m) <= set('xrwab+'))","tryCatchPattern":"try:\n    f = io.FileIO(path, mode)\nexcept ValueError as e:\n    if 'exactly one' in str(e):\n        f = io.FileIO(path, 'r+b')  # read-write default\n    else:\n        raise","preventionTips":["Remember '+' grants the second direction; 'rw' is never a mode","Whitelist-validate modes from config against a fixed set","Use open() for combined buffered use; it applies the same rule early with clearer docs"],"tags":["python","io","file-io","mode","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}