mastra-ai/mastra · error · RangeError
maxRetainedBytes must be a non-negative integer or Infinity
Error message
maxRetainedBytes must be a non-negative integer or Infinity
What it means
validateMaxRetainedProcessOutputBytes enforces that maxRetainedProcessOutputBytes is a non-negative integer or Infinity. Any NaN, fractional, negative, or non-numeric value (other than Infinity) throws this RangeError at ProcessHandle construction.
Source
Thrown at packages/core/src/workspace/sandbox/process-manager/process-handle.ts:22
* Abstract base class for process handles.
* Manages stdout/stderr callback dispatch and provides lazy
* reader/writer stream getters — subclasses only implement
* the platform-specific primitives.
*/
import { Readable, Writable } from 'node:stream';
import type { CommandResult } from '../types';
import type { SpawnProcessOptions } from './types';
export const DEFAULT_MAX_RETAINED_PROCESS_OUTPUT_BYTES = 1024 * 1024;
const RETAINED_OUTPUT_COMPACT_CHUNK_THRESHOLD = 128;
/** @internal */
export function validateMaxRetainedProcessOutputBytes(maxRetainedBytes: number): number {
if (maxRetainedBytes === Infinity) return maxRetainedBytes;
if (!Number.isFinite(maxRetainedBytes) || maxRetainedBytes < 0 || !Number.isInteger(maxRetainedBytes)) {
throw new RangeError('maxRetainedBytes must be a non-negative integer or Infinity');
}
return maxRetainedBytes;
}
function advanceStartByUtf8Bytes(
value: string,
start: number,
minimumBytesToDrop: number,
): { start: number; droppedBytes: number } {
let nextStart = start;
let droppedBytes = 0;
while (nextStart < value.length && droppedBytes < minimumBytesToDrop) {
const codePoint = value.codePointAt(nextStart)!;
if (codePoint < 0x80) droppedBytes += 1;
else if (codePoint < 0x800) droppedBytes += 2;
else if (codePoint < 0x10000) droppedBytes += 3;View on GitHub (pinned to 75dd419e61)
Solutions
- Pass a non-negative integer (e.g. 5 * 1024 * 1024) or Infinity.
- Coerce string config values with Number()/parseInt before passing.
- Round computed limits with Math.floor().
Example fix
// before
new ProcessHandle({ maxRetainedProcessOutputBytes: opts.retainedOutput }); // '5242880' string
// after
const n = Number(opts.retainedOutput);
new ProcessHandle({
maxRetainedProcessOutputBytes: Number.isFinite(n) ? Math.max(0, Math.floor(n)) : Infinity,
}); Defensive patterns
Strategy: validation
Validate before calling
function isValidRetainedBytes(v: unknown): v is number {
return v === Infinity || (typeof v === 'number' && Number.isInteger(v) && v >= 0);
}
if (!isValidRetainedBytes(opts.maxRetainedProcessOutputBytes)) {
throw new TypeError('maxRetainedProcessOutputBytes must be a non-negative integer or Infinity');
} Type guard
function isNonNegIntOrInfinity(v: unknown): v is number {
return v === Infinity || (typeof v === 'number' && Number.isSafeInteger(v) && v >= 0);
} Try / catch
try {
handle = new ProcessHandle({ maxRetainedProcessOutputBytes: raw });
} catch (e) {
if (e instanceof RangeError && /maxRetainedBytes/.test(e.message)) {
handle = new ProcessHandle({ maxRetainedProcessOutputBytes: 1024 * 1024 });
} else throw e;
} Prevention
- Coerce and floor config values from env/CLI to safe integers before use.
- Use integer math (n * 1024 * 1024) rather than fractional multipliers for byte limits.
- Validate with Number.isSafeInteger at config-loading time, not at construction.
When it happens
Trigger: Constructing a ProcessHandle (or passing a process option) with e.g. maxRetainedBytes: -1, 10.5, '1MB', NaN, or null.
Common situations: Parsing a config value from env/CLI as a string instead of a number; computing a byte limit with arithmetic that yields a float (e.g. bytes = 0.5 * MB); typos like `1024 * 1024,` producing a non-integer expression result.
Understand the failure class
Background: "must be positive", "Invalid value": how libraries reject invalid parameter values (ValueError, ArgumentError, INVALID_PARAMETER_VALUE) — this error's family across 28 libraries.
Related errors
- heartbeatMs must be a finite number no greater than ${MAX_TI
- ClaudeSDKAgent resumeData must include sessionId or continue
- CursorSDKAgent resumeData must include a message.
- CursorSDKAgent resumeData.agentId must be a string when prov
- CursorSDKAgent does not support structuredOutput because the
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/9d9fd3e272359e5a.
Report an issue: GitHub.