pydantic/monty · error · TypeError

MontyFileHandle position must be a non-negative safe integer

Error message

MontyFileHandle position must be a non-negative safe integer

What it means

The position passed to a MontyFileHandle must be a JavaScript number that is a non-negative safe integer (<= Number.MAX_SAFE_INTEGER) so it crosses the JS/WASM boundary exactly. validateFilePosition throws this TypeError for anything else — non-numbers, NaN, negatives, floats, or integers above 2^53-1.

Source

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

      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')
  }
  return `${action}${binary ? 'b' : ''}`
}

/** Validates that a file position can cross the JavaScript boundary exactly. */
export function validateFilePosition(position: unknown): asserts position is number {
  if (typeof position !== 'number' || !Number.isSafeInteger(position) || position < 0) {
    throw new TypeError('MontyFileHandle position must be a non-negative safe integer')
  }
}

View on GitHub (pinned to adc986b362)

Solutions

  1. Ensure the value is a non-negative integer before passing: `Math.max(0, Math.trunc(offset))`
  2. Convert string values with `Number(str)` and validate with Number.isSafeInteger
  3. For offsets beyond Number.MAX_SAFE_INTEGER, the binding cannot represent them — restructure to avoid such offsets or track them in chunks

Example fix

// before
fh.seek(BigInt(offset))
// after
const pos = Number(offset)
if (!Number.isSafeInteger(pos) || pos < 0) throw new Error('bad offset')
fh.seek(pos)
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidPosition(p) { return typeof p === 'number' && Number.isSafeInteger(p) && p >= 0 }

Type guard

function isFilePosition(p) { return typeof p === 'number' && Number.isSafeInteger(p) && p >= 0 }

Try / catch

try { fh.seek(pos) } catch (e) { if (e instanceof TypeError && e.message.includes('non-negative safe integer')) throw new Error(`bad file position: ${String(pos)}`) ; throw e }

Prevention

When it happens

Trigger: Calling MontyFileHandle's constructor or pushFileHandle with position = -1, 1.5, '10' (string), NaN, or a 64-bit offset from a host file larger than 2^53 bytes.

Common situations: Reading a seek offset from config/JSON where it arrives as a string; computing offsets with arithmetic that yields floats; files whose sizes exceed safe-integer range (rare but possible with large host files).

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


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