{"record":{"id":"6e79d03d56b269b9","repo":"pydantic/monty","slug":"invalid-mode-binary-mode-specified-twice","errorCode":null,"errorMessage":"invalid mode: binary mode specified twice","messagePattern":"invalid mode: binary mode specified twice","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/types.ts","lineNumber":135,"sourceCode":"}\n\n/** Canonicalizes the subset of Python file modes Monty supports. */\nexport function canonicalFileMode(mode: string): string {\n  if (mode.length === 0) {\n    throw new TypeError('Must have exactly one of create/read/write/append mode and at most one plus')\n  }\n\n  let action: string | undefined\n  let binary = false\n  let text = false\n  for (const char of mode) {\n    if (char === 'r' || char === 'w' || char === 'a') {\n      if (action !== undefined) throw new TypeError('must have exactly one of create/read/write/append mode')\n      action = char\n    } else if (char === 'x') {\n      throw new TypeError('exclusive creation mode is not supported')\n    } else if (char === 'b') {\n      if (binary) throw new TypeError('invalid mode: binary mode specified twice')\n      binary = true\n    } else if (char === 't') {\n      if (text) throw new TypeError('invalid mode: text mode specified twice')\n      text = true\n    } else if (char === '+') {\n      throw new TypeError(\"update modes ('+') are not yet supported\")\n    } else {\n      throw new TypeError(`invalid mode: '${char}'`)\n    }\n  }\n  if (binary && text) throw new TypeError(\"can't have text and binary mode at once\")\n  if (action === undefined) {\n    throw new TypeError('Must have exactly one of create/read/write/append mode and at most one plus')\n  }\n  return `${action}${binary ? 'b' : ''}`\n}\n\n/** Validates that a file position can cross the JavaScript boundary exactly. */","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/types.ts#L117-L153","documentation":"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.","triggerScenarios":"Passing a mode like 'rbb', 'wb+', 'bwb' (any string where a second 'b' is scanned) to MontyFileHandle's constructor or pushFileHandle.","commonSituations":"Programmatic mode-string assembly where 'b' is appended twice (e.g. base mode + flags both adding 'b'); typo'd concatenated constants.","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"],"exampleFix":"// before\nconst mode = base + 'b' // base already 'rb'\n// after\nconst mode = base.endsWith('b') ? base : base + 'b'","handlingStrategy":"validation","validationCode":"if (typeof mode === 'string' && (mode.match(/b/g) || []).length > 1) throw new Error('mode has duplicate b')","typeGuard":"function hasSingleB(mode) { return typeof mode === 'string' && (mode.match(/b/g) || []).length <= 1 }","tryCatchPattern":"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 }","preventionTips":["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"],"tags":["typescript","file-mode","duplicate-flag"],"backgroundTag":"invalid-argument-format","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}