{"record":{"id":"e0e0d692271e09bc","repo":"pydantic/monty","slug":"montyfilehandle-position-exceeds-javascript-s-maximum-safe","errorCode":null,"errorMessage":"MontyFileHandle position exceeds JavaScript's maximum safe integer","messagePattern":"MontyFileHandle position exceeds JavaScript's maximum safe integer","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/worker/value.ts","lineNumber":355,"sourceCode":"    case 'exception':\n      value = { [TYPE_MARKER]: 'Exception', excType: node.val.excType, message: node.val.message ?? '' }\n      break\n    case 'type-name':\n      value = { [TYPE_MARKER]: 'Type', value: node.val }\n      break\n    case 'class-type':\n      value = { [TYPE_MARKER]: 'Type', classType: readClassType(node.val, nodes, visiting) }\n      break\n    case 'builtin-function':\n      value = { [TYPE_MARKER]: 'BuiltinFunction', value: node.val }\n      break\n    case 'path':\n    case 'repr':\n      value = node.val\n      break\n    case 'file-handle':\n      if (node.val.position > BigInt(Number.MAX_SAFE_INTEGER)) {\n        throw new TypeError(\"MontyFileHandle position exceeds JavaScript's maximum safe integer\")\n      }\n      value = new MontyFileHandle(node.val.path, node.val.mode, { position: Number(node.val.position) })\n      break\n    case 'class-instance':\n      value = readClassInstance(node.val, nodes, visiting)\n      break\n    case 'function':\n      value = node.val.name\n      break\n    case 'cycle':\n      value = node.val.placeholder\n      break\n  }\n  visiting.delete(index)\n  return value\n}\n\n/** Reads child indexes into a JavaScript array. */","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/worker/value.ts#L337-L373","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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)","Inspect the Python code for seek() calls with astronomically large offsets and correct them","If a large position is genuinely needed, represent the position as a string/BigInt on the host side (would require a library change)"],"exampleFix":"// before (sandbox python)\nf = open('/mnt/data/log.txt', 'r')\nf.seek(10**20)  # position exceeds 2**53-1\n\n// after\nf = open('/mnt/data/log.txt', 'r')\nf.seek(0, 2)  # seek relative to real end; position stays in safe range","handlingStrategy":"validation","validationCode":"function assertSafePosition(handle) {\n  if (handle.position !== undefined && BigInt(handle.position) > BigInt(Number.MAX_SAFE_INTEGER)) {\n    throw new RangeError('file position exceeds MAX_SAFE_INTEGER');\n  }\n}\nassertSafePosition(result.fileHandle);","typeGuard":"function hasSafePosition(v) {\n  return v?.position === undefined ||\n    (typeof v.position === 'number' && Number.isSafeInteger(v.position)) ||\n    (typeof v.position === 'bigint' && v.position <= BigInt(Number.MAX_SAFE_INTEGER));\n}","tryCatchPattern":"try {\n  const value = decode(node);\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('maximum safe integer')) {\n    // re-seek in sandbox or handle position as BigInt/string\n  } else { throw e; }\n}","preventionTips":["Avoid seek() to offsets beyond 2**53-1 in sandbox code","Seek relative to the real file end (seek(0, 2)) instead of absolute giant offsets","Validate any computed seek offsets before use"],"tags":["javascript","bigint","file-handle","value-conversion"],"backgroundTag":"value-out-of-range","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}