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

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)

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.