pydantic/monty · error · TypeError

can't have text and binary mode at once

Error message

can't have text and binary mode at once

What it means

The mode string combined both 'b' (binary) and 't' (text), which is contradictory — a file is opened either in binary or text mode, never both. canonicalFileMode checks this after the character loop and throws a TypeError.

Source

Thrown at crates/monty-js/ts/types.ts:146

  for (const char of mode) {
    if (char === 'r' || char === 'w' || char === 'a') {
      if (action !== undefined) throw new TypeError('must have exactly one of create/read/write/append mode')
      action = char
    } else if (char === 'x') {
      throw new TypeError('exclusive creation mode is not supported')
    } else if (char === 'b') {
      if (binary) throw new TypeError('invalid mode: binary mode specified twice')
      binary = true
    } else if (char === 't') {
      if (text) throw new TypeError('invalid mode: text mode specified twice')
      text = true
    } else if (char === '+') {
      throw new TypeError("update modes ('+') are not yet supported")
    } else {
      throw new TypeError(`invalid mode: '${char}'`)
    }
  }
  if (binary && text) throw new TypeError("can't have text and binary mode at once")
  if (action === undefined) {
    throw new TypeError('Must have exactly one of create/read/write/append mode and at most one plus')
  }
  return `${action}${binary ? 'b' : ''}`
}

/** Validates that a file position can cross the JavaScript boundary exactly. */
export function validateFilePosition(position: unknown): asserts position is number {
  if (typeof position !== 'number' || !Number.isSafeInteger(position) || position < 0) {
    throw new TypeError('MontyFileHandle position must be a non-negative safe integer')
  }
}

View on GitHub (pinned to adc986b362)

Solutions

  1. Remove either 'b' or 't' from the mode string — text mode is the default, so just drop 't'
  2. Decide the mode once based on a boolean: `binary ? 'rb' : 'r'`
  3. Validate/normalize user-supplied modes before combining them with defaults

Example fix

// before
const mode = 'rb' + 't'
// after
const mode = 'rb'
Defensive patterns

Strategy: validation

Validate before calling

if (typeof mode === 'string' && mode.includes('b') && mode.includes('t')) throw new Error('mode cannot specify both b and t')

Type guard

function isUnambiguousMode(mode) { return typeof mode === 'string' && !(mode.includes('b') && mode.includes('t')) }

Try / catch

try { fh = new MontyFileHandle(path, mode) } catch (e) { if (e instanceof TypeError && e.message.includes("text and binary mode at once")) fh = new MontyFileHandle(path, mode.replace('t', '')) ; else throw e }

Prevention

When it happens

Trigger: Passing modes like 'rbt', 'wbt', 'tbr' to MontyFileHandle's constructor or pushFileHandle.

Common situations: Programmatic mode assembly that unconditionally appends 't' as a default even when the base mode already requested binary; concatenating user flags with a hardcoded 'b'.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/d01d1616c95f460f. Report an issue: GitHub.