pydantic/monty · error · TypeError

MontyFileHandle path must be a string

Error message

MontyFileHandle path must be a string

What it means

The `MontyFileHandle` constructor validates that the `path` argument is a JavaScript string, since the handle is returned from an `open` OS callback and the wire protocol requires a textual virtual path. Passing a non-string (number, Path object, undefined, etc.) is rejected up front with a TypeError.

Source

Thrown at crates/monty-js/ts/types.ts:84

}

/**
 * Host-side handle to a file opened inside a Monty sandbox.
 *
 * This is a plain data holder, never a live host file descriptor. Return one
 * from an `open` OS callback so Monty can construct its sandboxed file object.
 */
export class MontyFileHandle {
  /** Virtual POSIX sandbox path, never a host path. */
  readonly path: string
  /** Canonical Python `open()` mode, such as `'r'`, `'rb'`, or `'w'`. */
  readonly mode: string
  /** Current character or byte position. */
  readonly position: number

  /** Constructs a file handle to return from an `open` OS callback. */
  constructor(path: string, mode: string, options: MontyFileHandleOptions = {}) {
    if (typeof path !== 'string') throw new TypeError('MontyFileHandle path must be a string')
    if (typeof mode !== 'string') throw new TypeError('MontyFileHandle mode must be a string')
    const position = options.position ?? 0
    validateFilePosition(position)

    this.path = path
    this.mode = canonicalFileMode(mode)
    this.position = position
    Object.defineProperty(this, '__monty_type__', { value: 'FileHandle' })
    Object.freeze(this)
  }

  /** Whether the mode opens the file in binary form. */
  get binary(): boolean {
    return this.mode.includes('b')
  }

  /** Whether the mode permits reads. */
  get readable(): boolean {

View on GitHub (pinned to adc986b362)

Solutions

  1. Coerce/validate the path to a string before constructing: `new MontyFileHandle(String(path), mode)` only if a string is truly intended.
  2. Check where the value comes from — the OS callback should pass its `path` field, not the whole request object.
  3. Add `typeof path === 'string'` validation at the callback boundary.

Example fix

// before
const handle = new MontyFileHandle(request, mode); // request object, not string

// after
const handle = new MontyFileHandle(request.path, mode);
Defensive patterns

Strategy: validation

Validate before calling

function assertString(v, name) { if (typeof v !== 'string') throw new TypeError(`${name} must be a string`); return v; }
assertString(path, 'path');

Type guard

const isPath = (v: unknown): v is string => typeof v === 'string' && v.length > 0;

Try / catch

try {
  return new MontyFileHandle(path, mode);
} catch (e) {
  if (e instanceof TypeError && /must be a string/.test(e.message)) {
    throw new TypeError(`open callback got invalid path: ${typeof path}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Constructing `new MontyFileHandle(path, mode)` inside an `open` OS callback where `path` came from loosely typed input — e.g. destructured callback args, a `Path`-like object, a number, or `undefined` from a missing argument.

Common situations: Host callback code receives the open request as an untyped/`any` value (or from JS after a refactor) and forwards it directly; TypeScript compilation is skipped or the value was cast.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/7df0c8991b5cde9a. Report an issue: GitHub.