juicedata/juicefs · error · ValueError

can't have text and binary mode at once

Error message

can't have text and binary mode at once

What it means

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().

Solutions

  1. Remove either 't' or 'b' from the mode — keep only one.
  2. If raw bytes are needed use 'rb'; if decoded str is needed use 'r' or 'rt'.
  3. Sanitize programmatically assembled modes to at most one of t/b.

Example fix

# before
f = jfs.open(path, 'rbt')
# after
f = jfs.open(path, 'rb')  # binary, or 'r' for text
Defensive patterns

Strategy: validation

Validate before calling

if 'b' in mode and 't' in mode:
    raise ValueError("mode cannot contain both 'b' and 't'")

Type guard

def is_valid_textuality(mode) -> bool:
    return not ('b' in mode and 't' in mode)

Try / catch

try:
    f = jfs.open(path, mode)
except ValueError as e:
    if 'text and binary' in str(e):
        mode = mode.replace('t', '')
        f = jfs.open(path, mode)
    else:
        raise

Prevention

When it happens

Trigger: open(path, 'rbt'), open(path, 'w+b+t') or any mode containing both 'b' and 't'.

Common situations: 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.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/795dab99647983b1. Report an issue: GitHub.

Appendix: source

Thrown at sdk/python/juicefs/juicefs/juicefs.py:223

            raise ValueError(f'invalid mode: {mode}')
        flag = 0
        cnt = 0
        for c in mode:
            if c in 'rwxa':
                cnt += 1
                if c == 'r':
                    flag |= MODE_READ
                else:
                    flag |= MODE_WRITE
            elif c == '+':
                flag |= MODE_READ | MODE_WRITE
            elif c not in 'tb':
                raise ValueError(f'invalid mode: {mode}')
        if cnt != 1:
            raise ValueError('must have exactly one of create/read/write/append mode')
        if 'b' in mode:
            if 't' in mode:
                raise ValueError("can't have text and binary mode at once")
            if encoding:
                raise ValueError("binary mode doesn't take an encoding argument")
            if errors:
                raise ValueError("binary mode doesn't take an errors argument")
        else:
            if not encoding:
                encoding = locale.getpreferredencoding(False).lower()
            if not errors:
                errors = 'strict'
            codecs.lookup(encoding)

        size = 0
        if 'x' in mode:
            fd = self.lib.jfs_create(c_int64(_tid()), c_int64(self.h), _bin(path), c_uint16(0o666), c_uint16(self.umask))
        else:
            try:
                sz = c_uint64()
                fd = self.lib.jfs_open_posix(c_int64(_tid()), c_int64(self.h), _bin(path), byref(sz), c_int32(flag))

View on GitHub (pinned to c9a67b23e8)