pydantic/monty · error · MontyRuntimeError
MemoryError
MemoryError
Error message
memory limit exceeded: ${used} bytes > ${maxBytes} bytes What it means
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.
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
Example fix
// before
const collector = new PrintCollector({ maxBytes: 1024 }) // too small for the run
// after
const collector = new PrintCollector({ maxBytes: 10 * 1024 * 1024 }) // 10 MiB, or null for no cap Defensive patterns
Strategy: try-catch
Try / catch
try {
const text = await session.feedRun(code, { printCallback: collector.write.bind(collector) })
} catch (e) {
if (e instanceof MontyRuntimeError && e.code === 'MemoryError' && e.message.startsWith('memory limit exceeded')) {
// flush what was collected so far, raise cap, or stream to disk
} else throw e
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- assertMessageAnnotations must be a boolean or an integer…
- at least one OpenTelemetry component is required
- can't have text and binary mode at once
- Cannot convert instance to a Monty value — wrap it in…
- ClassInstance attr name must be a string
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/734264c03e7ecdd0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/monty-js/ts/print.ts:37
const utf8Encoder = new TextEncoder()
/** UTF-8 byte length of `text` (parity with Rust/Python `str`/`String` len). */
function utf8Len(text: string): number {
return utf8Encoder.encode(text).byteLength
}
/**
* Reject collect growth past `maxBytes`.
* `null` = unlimited. Message must match ResourceError::Memory / check_print_collect_limit exactly.
* Package-internal — do not re-export from index/node/wasm.
*/
function checkPrintCollectLimit(current: number, add: number, maxBytes: number | null): void {
if (maxBytes === null) return
// Caps stay far below Number.MAX_SAFE_INTEGER; plain + is exact for our sizes.
const used = current + add
if (used > maxBytes) {
throw new MontyRuntimeError('MemoryError', `memory limit exceeded: ${used} bytes > ${maxBytes} bytes`)
}
}
/**
* Normalize constructor `maxBytes`: only `null` disables the cap.
* Rejects NaN/Infinity (which would make `used > maxBytes` never true) and negatives.
*/
function resolveMaxBytes(maxBytes: number | null): number | null {
if (maxBytes === null) return null
if (typeof maxBytes !== 'number' || !Number.isFinite(maxBytes) || maxBytes < 0) {
throw new TypeError('maxBytes must be a finite non-negative number or null')
}
return maxBytes
}
/**
* Accumulates print fragments into one string. Pass as `printCallback`.
* Default cap: DEFAULT_MAX_PRINT_COLLECT_BYTES. Pass maxBytes: null to disable.View on GitHub (pinned to adc986b362)