pydantic/monty · error · TypeError
must have exactly one of create/read/write/append mode
Error message
must have exactly one of create/read/write/append mode
What it means
`canonicalFileMode` requires exactly one primary action character ('r', 'w', or 'a'); encountering a second one raises this TypeError. This matches CPython's message for invalid combinations of open-mode action characters.
Source
Thrown at crates/monty-js/ts/types.ts:130
static [Symbol.hasInstance](value: unknown): boolean {
return (
typeof value === 'object' && value !== null && (value as Record<string, unknown>).__monty_type__ === 'FileHandle'
)
}
}
/** 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')View on GitHub (pinned to adc986b362)
Solutions
- Use exactly one action character: 'r', 'w', or 'a', plus at most one '+' (e.g. 'r+', 'w+', 'a+').
- Fix flag-concatenation code so it picks a single base action instead of appending multiple.
- If read+write is intended, use 'r+' (or 'w+' to truncate).
Example fix
// before new MontyFileHandle(path, 'rw'); // after new MontyFileHandle(path, 'r+');
Defensive patterns
Strategy: validation
Validate before calling
const actions = [...mode].filter(c => 'rwa'.includes(c)).length;
if (actions !== 1) throw new TypeError(`mode must contain exactly one of r/w/a, got '${mode}'`); Try / catch
try {
return new MontyFileHandle(path, mode);
} catch (e) {
if (e instanceof TypeError && e.message === 'must have exactly one of create/read/write/append mode') {
throw new TypeError(`unsupported mode '${mode}'; use r/w/a with optional +`);
}
throw e;
} Prevention
- Remember Python open modes are not C fopen modes: 'rw' is invalid, use 'r+'
- Build modes from one base action plus flags, never by appending multiple actions
- Map user-supplied intents (read/write/append) to a fixed mode table
When it happens
Trigger: Calling `new MontyFileHandle(path, 'rw')`, `'ra'`, `'wr'`, etc. — a mode containing two action characters. Note 'x' (exclusive creation) raises a different error.
Common situations: Devs familiar with C's fopen accept strings like 'rw+' assume Python accepts them; or mode strings are built by concatenating per-feature flags without ensuring only one action.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Must have exactly one of create/read/write/append mode and a
- Max input depth exceeded
- ClassInstance marker instanceId must be a uuid string
- ${field} must be 'all', undefined or a list/Set of names, go
- memoryUsageLimit must be a non-negative safe integer
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/803b3488daf3710e.
Report an issue: GitHub.