{"record":{"id":"795dab99647983b1","repo":"juicedata/juicefs","slug":"can-t-have-text-and-binary-mode-at-once","errorCode":null,"errorMessage":"can't have text and binary mode at once","messagePattern":"can't have text and binary mode at once","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdk/python/juicefs/juicefs/juicefs.py","lineNumber":223,"sourceCode":"            raise ValueError(f'invalid mode: {mode}')\n        flag = 0\n        cnt = 0\n        for c in mode:\n            if c in 'rwxa':\n                cnt += 1\n                if c == 'r':\n                    flag |= MODE_READ\n                else:\n                    flag |= MODE_WRITE\n            elif c == '+':\n                flag |= MODE_READ | MODE_WRITE\n            elif c not in 'tb':\n                raise ValueError(f'invalid mode: {mode}')\n        if cnt != 1:\n            raise ValueError('must have exactly one of create/read/write/append mode')\n        if 'b' in mode:\n            if 't' in mode:\n                raise ValueError(\"can't have text and binary mode at once\")\n            if encoding:\n                raise ValueError(\"binary mode doesn't take an encoding argument\")\n            if errors:\n                raise ValueError(\"binary mode doesn't take an errors argument\")\n        else:\n            if not encoding:\n                encoding = locale.getpreferredencoding(False).lower()\n            if not errors:\n                errors = 'strict'\n            codecs.lookup(encoding)\n\n        size = 0\n        if 'x' in mode:\n            fd = self.lib.jfs_create(c_int64(_tid()), c_int64(self.h), _bin(path), c_uint16(0o666), c_uint16(self.umask))\n        else:\n            try:\n                sz = c_uint64()\n                fd = self.lib.jfs_open_posix(c_int64(_tid()), c_int64(self.h), _bin(path), byref(sz), c_int32(flag))","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/sdk/python/juicefs/juicefs/juicefs.py#L205-L241","documentation":"A mode cannot request both text ('t') and binary ('b') handling; they are mutually exclusive text-decoding strategies. open() checks this when 'b' is present in the mode and raises ValueError if 't' is also present, exactly like CPython's builtin open().","triggerScenarios":"open(path, 'rbt'), open(path, 'w+b+t') or any mode containing both 'b' and 't'.","commonSituations":"Concatenating 'b' from one code path and 't' from another; template mode strings like 'r{mode}' filled with 'bt'; copying modes between text/binary contexts without stripping the old flag.","solutions":["Remove either 't' or 'b' from the mode — keep only one.","If raw bytes are needed use 'rb'; if decoded str is needed use 'r' or 'rt'.","Sanitize programmatically assembled modes to at most one of t/b."],"exampleFix":"# before\nf = jfs.open(path, 'rbt')\n# after\nf = jfs.open(path, 'rb')  # binary, or 'r' for text","handlingStrategy":"validation","validationCode":"if 'b' in mode and 't' in mode:\n    raise ValueError(\"mode cannot contain both 'b' and 't'\")","typeGuard":"def is_valid_textuality(mode) -> bool:\n    return not ('b' in mode and 't' in mode)","tryCatchPattern":"try:\n    f = jfs.open(path, mode)\nexcept ValueError as e:\n    if 'text and binary' in str(e):\n        mode = mode.replace('t', '')\n        f = jfs.open(path, mode)\n    else:\n        raise","preventionTips":["When assembling modes dynamically, set at most one of 't'/'b'.","Prefer omitting both flags (default is text) or just use 'b' for bytes.","Centralize mode construction in one helper that enforces exclusivity."],"tags":["python","file-open","mutually-exclusive"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}