{"record":{"id":"d01d1616c95f460f","repo":"pydantic/monty","slug":"can-t-have-text-and-binary-mode-at-once","errorCode":null,"errorMessage":"can't have text and binary mode at once","messagePattern":"can't have text and binary mode at once","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/types.ts","lineNumber":146,"sourceCode":"  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. */\nexport function validateFilePosition(position: unknown): asserts position is number {\n  if (typeof position !== 'number' || !Number.isSafeInteger(position) || position < 0) {\n    throw new TypeError('MontyFileHandle position must be a non-negative safe integer')\n  }\n}\n","sourceCodeStart":128,"sourceCodeEnd":159,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/types.ts#L128-L159","documentation":"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.","triggerScenarios":"Passing modes like 'rbt', 'wbt', 'tbr' to MontyFileHandle's constructor or pushFileHandle.","commonSituations":"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'.","solutions":["Remove either 'b' or 't' from the mode string — text mode is the default, so just drop 't'","Decide the mode once based on a boolean: `binary ? 'rb' : 'r'`","Validate/normalize user-supplied modes before combining them with defaults"],"exampleFix":"// before\nconst mode = 'rb' + 't'\n// after\nconst mode = 'rb'","handlingStrategy":"validation","validationCode":"if (typeof mode === 'string' && mode.includes('b') && mode.includes('t')) throw new Error('mode cannot specify both b and t')","typeGuard":"function isUnambiguousMode(mode) { return typeof mode === 'string' && !(mode.includes('b') && mode.includes('t')) }","tryCatchPattern":"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 }","preventionTips":["Choose text or binary with a single boolean and construct the mode from it","Never merge independently sourced mode fragments","Note 't' is redundant — omit it entirely"],"tags":["typescript","file-mode","conflicting-options"],"backgroundTag":"conflicting-config-options","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"}