{"record":{"id":"734264c03e7ecdd0","repo":"pydantic/monty","slug":"memoryerror","errorCode":"MemoryError","errorMessage":"memory limit exceeded: ${used} bytes > ${maxBytes} bytes","messagePattern":"memory limit exceeded: (.+?) bytes > (.+?) bytes","errorType":"error_code","errorClass":"MontyRuntimeError","httpStatus":null,"severity":"error","filePath":"crates/monty-js/ts/print.ts","lineNumber":37,"sourceCode":"\nconst utf8Encoder = new TextEncoder()\n\n/** UTF-8 byte length of `text` (parity with Rust/Python `str`/`String` len). */\nfunction utf8Len(text: string): number {\n  return utf8Encoder.encode(text).byteLength\n}\n\n/**\n * Reject collect growth past `maxBytes`.\n * `null` = unlimited. Message must match ResourceError::Memory / check_print_collect_limit exactly.\n * Package-internal — do not re-export from index/node/wasm.\n */\nfunction checkPrintCollectLimit(current: number, add: number, maxBytes: number | null): void {\n  if (maxBytes === null) return\n  // Caps stay far below Number.MAX_SAFE_INTEGER; plain + is exact for our sizes.\n  const used = current + add\n  if (used > maxBytes) {\n    throw new MontyRuntimeError('MemoryError', `memory limit exceeded: ${used} bytes > ${maxBytes} bytes`)\n  }\n}\n\n/**\n * Normalize constructor `maxBytes`: only `null` disables the cap.\n * Rejects NaN/Infinity (which would make `used > maxBytes` never true) and negatives.\n */\nfunction resolveMaxBytes(maxBytes: number | null): number | null {\n  if (maxBytes === null) return null\n  if (typeof maxBytes !== 'number' || !Number.isFinite(maxBytes) || maxBytes < 0) {\n    throw new TypeError('maxBytes must be a finite non-negative number or null')\n  }\n  return maxBytes\n}\n\n/**\n * Accumulates print fragments into one string. Pass as `printCallback`.\n * Default cap: DEFAULT_MAX_PRINT_COLLECT_BYTES. Pass maxBytes: null to disable.","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty-js/ts/print.ts#L19-L55","documentation":"A print-collector accumulated more bytes than its configured `maxBytes` cap, so `write` refuses the fragment and raises `MontyRuntimeError` with code `MemoryError`. This protects the host from unbounded output growth when collecting print output from sandboxed code.","triggerScenarios":"Sandboxed code printing more total bytes than the collector's `maxBytes` (set in the constructor or per-feed print options); the throw happens inside `printCallback`/`write`, which typically aborts the running turn.","commonSituations":"Debug loops printing per-item in a large batch (10k lines), a worker emitting progress output in a loop, cap set for testing then code run against a large dataset.","solutions":["Raise `maxBytes` when constructing the collector (or pass `null` to disable the cap)","Reduce or batch the printed output in the sandboxed code","Catch `MontyRuntimeError` in the print callback and stream fragments to disk/remote instead of accumulating in memory"],"exampleFix":"// before\nconst collector = new PrintCollector({ maxBytes: 1024 }) // too small for the run\n// after\nconst collector = new PrintCollector({ maxBytes: 10 * 1024 * 1024 }) // 10 MiB, or null for no cap","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const text = await session.feedRun(code, { printCallback: collector.write.bind(collector) })\n} catch (e) {\n  if (e instanceof MontyRuntimeError && e.code === 'MemoryError' && e.message.startsWith('memory limit exceeded')) {\n    // flush what was collected so far, raise cap, or stream to disk\n  } else throw e\n}","preventionTips":["Size maxBytes above the worst-case output of the workload (log it in staging)","Stream output incrementally instead of accumulating when volume is unbounded","Set maxBytes to null only for trusted workloads — the cap exists to protect the host"],"tags":["typescript","resource-limit","memory"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}