{"record":{"id":"c6ffc1fe5b8f2615","repo":"pydantic/monty","slug":"montyfilehandle-mode-must-be-a-string","errorCode":null,"errorMessage":"MontyFileHandle mode must be a string","messagePattern":"MontyFileHandle mode must be a string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/types.ts","lineNumber":85,"sourceCode":"\n/**\n * Host-side handle to a file opened inside a Monty sandbox.\n *\n * This is a plain data holder, never a live host file descriptor. Return one\n * from an `open` OS callback so Monty can construct its sandboxed file object.\n */\nexport class MontyFileHandle {\n  /** Virtual POSIX sandbox path, never a host path. */\n  readonly path: string\n  /** Canonical Python `open()` mode, such as `'r'`, `'rb'`, or `'w'`. */\n  readonly mode: string\n  /** Current character or byte position. */\n  readonly position: number\n\n  /** Constructs a file handle to return from an `open` OS callback. */\n  constructor(path: string, mode: string, options: MontyFileHandleOptions = {}) {\n    if (typeof path !== 'string') throw new TypeError('MontyFileHandle path must be a string')\n    if (typeof mode !== 'string') throw new TypeError('MontyFileHandle mode must be a string')\n    const position = options.position ?? 0\n    validateFilePosition(position)\n\n    this.path = path\n    this.mode = canonicalFileMode(mode)\n    this.position = position\n    Object.defineProperty(this, '__monty_type__', { value: 'FileHandle' })\n    Object.freeze(this)\n  }\n\n  /** Whether the mode opens the file in binary form. */\n  get binary(): boolean {\n    return this.mode.includes('b')\n  }\n\n  /** Whether the mode permits reads. */\n  get readable(): boolean {\n    return this.mode.startsWith('r') || this.mode.includes('+')","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/types.ts#L67-L103","documentation":"The `MontyFileHandle` constructor validates that the `mode` argument is a JavaScript string. The mode is the Python-style open mode (e.g. 'r', 'w', 'rb') which is canonicalized character by character, so non-string values cannot be accepted.","triggerScenarios":"Calling `new MontyFileHandle(path, mode)` where mode is `undefined` (forgotten argument), a number, an options object, or a non-string constant from a config.","commonSituations":"Callback code omits the mode or swaps the argument order (`new MontyFileHandle(mode, path)`); or the mode is read from untyped env/config input.","solutions":["Pass a valid mode string like 'r', 'w', 'a', 'rb'; check the argument order (path first, mode second).","Default explicitly when the mode is optional: `mode ?? 'r'` only after confirming a string is intended.","Validate with `typeof mode === 'string'` before constructing."],"exampleFix":"// before\nconst handle = new MontyFileHandle(path); // mode undefined\n\n// after\nconst handle = new MontyFileHandle(path, 'r');","handlingStrategy":"validation","validationCode":"function assertMode(v) { if (typeof v !== 'string') throw new TypeError('mode must be a string'); return v; }\nassertMode(mode);","typeGuard":"const isFileMode = (v: unknown): v is string => typeof v === 'string' && /^[rwaxb+t]*$/.test(v);","tryCatchPattern":"try {\n  return new MontyFileHandle(path, mode);\n} catch (e) {\n  if (e instanceof TypeError && e.message === 'MontyFileHandle mode must be a string') {\n    return new MontyFileHandle(path, 'r'); // safe default\n  }\n  throw e;\n}","preventionTips":["Always pass mode as the second argument; path is first","Provide explicit default modes ('r' / 'rb') instead of omitting arguments","Type callback config so modes are typed as string literals"],"tags":["typescript","type-check","file-handle","constructor"],"backgroundTag":"type-mismatch","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"}