{"record":{"id":"599452b569c244f6","repo":"python/cpython","slug":"binary-mode-doesn-t-take-an-encoding-argument","errorCode":null,"errorMessage":"binary mode doesn't take an encoding argument","messagePattern":"binary mode doesn't take an encoding argument","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":223,"sourceCode":"        raise TypeError(\"invalid errors: %r\" % errors)\n    modes = set(mode)\n    if modes - set(\"axrwb+t\") or len(mode) > len(modes):\n        raise ValueError(\"invalid mode: %r\" % mode)\n    creating = \"x\" in modes\n    reading = \"r\" in modes\n    writing = \"w\" in modes\n    appending = \"a\" in modes\n    updating = \"+\" in modes\n    text = \"t\" in modes\n    binary = \"b\" in modes\n    if text and binary:\n        raise ValueError(\"can't have text and binary mode at once\")\n    if creating + reading + writing + appending > 1:\n        raise ValueError(\"can't have read/write/append mode at once\")\n    if not (creating or reading or writing or appending):\n        raise ValueError(\"must have exactly one of read/write/append mode\")\n    if binary and encoding is not None:\n        raise ValueError(\"binary mode doesn't take an encoding argument\")\n    if binary and errors is not None:\n        raise ValueError(\"binary mode doesn't take an errors argument\")\n    if binary and newline is not None:\n        raise ValueError(\"binary mode doesn't take a newline argument\")\n    if binary and buffering == 1:\n        import warnings\n        warnings.warn(\"line buffering (buffering=1) isn't supported in binary \"\n                      \"mode, the default buffer size will be used\",\n                      RuntimeWarning, 2)\n    raw = FileIO(file,\n                 (creating and \"x\" or \"\") +\n                 (reading and \"r\" or \"\") +\n                 (writing and \"w\" or \"\") +\n                 (appending and \"a\" or \"\") +\n                 (updating and \"+\" or \"\"),\n                 closefd, opener=opener)\n    result = raw\n    try:","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L205-L241","documentation":"Raised by io.open() as a ValueError when binary mode ('b') is combined with a non-None encoding argument. Binary streams carry raw bytes with no codec, so an encoding is meaningless and rejected to prevent silent misuse.","triggerScenarios":"open('f.bin', 'rb', encoding='utf-8'). Very common when encoding is passed unconditionally from a wrapper function (def read(path, encoding='utf-8'): open(path, 'rb', encoding=encoding)) while the mode is caller-controlled.","commonSituations":"Utility wrappers that always forward an encoding keyword; switching a file from text to binary mode while leaving the encoding argument in place; data-processing defaults like pd-adjacent code that threads encoding through every open call.","solutions":["In binary mode, drop the encoding argument (pass None or omit it).","In wrappers, forward encoding only for text mode: kwargs = {'encoding': enc} if 'b' not in mode else {}.","If you actually want decoding, use text mode ('r') instead of 'rb'."],"exampleFix":"// before\ndef load(path, encoding='utf-8'):\n    with open(path, 'rb', encoding=encoding) as f:  # ValueError\n        return f.read()\n\n// after\ndef load(path, encoding='utf-8', binary=False):\n    mode = 'rb' if binary else 'r'\n    kwargs = {} if binary else {'encoding': encoding}\n    with open(path, mode, **kwargs) as f:\n        return f.read()","handlingStrategy":"validation","validationCode":"def open_any(path, mode='r', encoding=None, errors=None, newline=None):\n    if 'b' in mode:\n        encoding = errors = newline = None      # strip text-only kwargs\n    return open(path, mode, encoding=encoding, errors=errors, newline=newline)","typeGuard":"def kwargs_ok_for_mode(mode: str, **kwargs) -> bool:\n    return 'b' not in mode or all(v is None for v in (kwargs.get('encoding'),))","tryCatchPattern":null,"preventionTips":["In wrappers, build a kwargs dict and only include encoding/errors/newline when 'b' not in mode.","Decide text vs binary first, then choose the argument set — never pass encoding unconditionally.","Add a unit test that opens every mode your helper accepts with its default arguments."],"tags":["io","open","encoding","binary-io","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}