pydantic/monty · error · TypeError
invalid mode: binary mode specified twice
Error message
invalid mode: binary mode specified twice
What it means
The mode string contained 'b' more than once (e.g. 'rbb' or 'wbb'), which is ambiguous/meaningless. canonicalFileMode validates each character and rejects duplicate binary flags with a TypeError, mirroring CPython's ValueError for invalid mode.
Source
Thrown at crates/monty-js/ts/types.ts:135
}
/** Canonicalizes the subset of Python file modes Monty supports. */
export function canonicalFileMode(mode: string): string {
if (mode.length === 0) {
throw new TypeError('Must have exactly one of create/read/write/append mode and at most one plus')
}
let action: string | undefined
let binary = false
let text = false
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. */View on GitHub (pinned to adc986b362)
Solutions
- Fix the mode construction so 'b' appears at most once, e.g. 'rb' not 'rbb'
- Deduplicate the mode characters before passing: `Array.from(new Set(mode)).join('')` (careful to preserve order)
- Log/inspect the mode string in the TypeError-adjacent call site to find the duplicate append
Example fix
// before
const mode = base + 'b' // base already 'rb'
// after
const mode = base.endsWith('b') ? base : base + 'b' Defensive patterns
Strategy: validation
Validate before calling
if (typeof mode === 'string' && (mode.match(/b/g) || []).length > 1) throw new Error('mode has duplicate b') Type guard
function hasSingleB(mode) { return typeof mode === 'string' && (mode.match(/b/g) || []).length <= 1 } Try / catch
try { fh = new MontyFileHandle(path, mode) } catch (e) { if (e instanceof TypeError && e.message.includes("binary mode specified twice")) fh = new MontyFileHandle(path, Array.from(new Set(mode)).join('')) ; else throw e } Prevention
- Build modes from a single canonical source, not by concatenating flags
- Normalize mode strings with deduplication before use
- Add a unit test over all mode strings your app can produce
When it happens
Trigger: Passing a mode like 'rbb', 'wb+', 'bwb' (any string where a second 'b' is scanned) to MontyFileHandle's constructor or pushFileHandle.
Common situations: Programmatic mode-string assembly where 'b' is appended twice (e.g. base mode + flags both adding 'b'); typo'd concatenated constants.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid mode: text mode specified twice
- exclusive creation mode is not supported
- update modes ('+') are not yet supported
- invalid mode: '${char}'
- can't have text and binary mode at once
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/6e79d03d56b269b9.
Report an issue: GitHub.