pydantic/monty · error · TypeError

MontyFileHandle position exceeds JavaScript's maximum safe i

Error message

MontyFileHandle position exceeds JavaScript's maximum safe integer

What it means

When converting a flat wire node tree into JavaScript values, a MontyFileHandle's stored position is a BigInt. JS numbers can only exactly represent integers up to Number.MAX_SAFE_INTEGER (2^53-1), so if the file handle's position exceeds that, the library throws a TypeError rather than silently losing precision. This protects callers from a corrupted position value.

Source

Thrown at crates/monty-js/ts/worker/value.ts:355

    case 'exception':
      value = { [TYPE_MARKER]: 'Exception', excType: node.val.excType, message: node.val.message ?? '' }
      break
    case 'type-name':
      value = { [TYPE_MARKER]: 'Type', value: node.val }
      break
    case 'class-type':
      value = { [TYPE_MARKER]: 'Type', classType: readClassType(node.val, nodes, visiting) }
      break
    case 'builtin-function':
      value = { [TYPE_MARKER]: 'BuiltinFunction', value: node.val }
      break
    case 'path':
    case 'repr':
      value = node.val
      break
    case 'file-handle':
      if (node.val.position > BigInt(Number.MAX_SAFE_INTEGER)) {
        throw new TypeError("MontyFileHandle position exceeds JavaScript's maximum safe integer")
      }
      value = new MontyFileHandle(node.val.path, node.val.mode, { position: Number(node.val.position) })
      break
    case 'class-instance':
      value = readClassInstance(node.val, nodes, visiting)
      break
    case 'function':
      value = node.val.name
      break
    case 'cycle':
      value = node.val.placeholder
      break
  }
  visiting.delete(index)
  return value
}

/** Reads child indexes into a JavaScript array. */

View on GitHub (pinned to adc986b362)

Solutions

  1. Seek the file handle back within the safe integer range before returning it to the host (e.g. re-seek near the actual end of the file)
  2. Inspect the Python code for seek() calls with astronomically large offsets and correct them
  3. If a large position is genuinely needed, represent the position as a string/BigInt on the host side (would require a library change)

Example fix

// before (sandbox python)
f = open('/mnt/data/log.txt', 'r')
f.seek(10**20)  # position exceeds 2**53-1

// after
f = open('/mnt/data/log.txt', 'r')
f.seek(0, 2)  # seek relative to real end; position stays in safe range
Defensive patterns

Strategy: validation

Validate before calling

function assertSafePosition(handle) {
  if (handle.position !== undefined && BigInt(handle.position) > BigInt(Number.MAX_SAFE_INTEGER)) {
    throw new RangeError('file position exceeds MAX_SAFE_INTEGER');
  }
}
assertSafePosition(result.fileHandle);

Type guard

function hasSafePosition(v) {
  return v?.position === undefined ||
    (typeof v.position === 'number' && Number.isSafeInteger(v.position)) ||
    (typeof v.position === 'bigint' && v.position <= BigInt(Number.MAX_SAFE_INTEGER));
}

Try / catch

try {
  const value = decode(node);
} catch (e) {
  if (e instanceof TypeError && e.message.includes('maximum safe integer')) {
    // re-seek in sandbox or handle position as BigInt/string
  } else { throw e; }
}

Prevention

When it happens

Trigger: Decoding a MontyObject result containing a MontyFileHandle whose seek/read position exceeds 9,007,199,254,740,991 — e.g. code that called file.seek() to a very large offset, or read a sparse/huge file far past 8 PB of logical position.

Common situations: Sandbox code seeking a file to an enormous offset (sparse files, tail writes to pseudo-large files), or host code passing positions around after many reads on a long-lived session. Practically rare, but a defensive guard against precision loss.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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