pydantic/monty · error · TypeError
invalid printFlushInterval: expected a non-negative number o
Error message
invalid printFlushInterval: expected a non-negative number of seconds, got ${interval} What it means
`printFlushInterval` is given in seconds and is converted to a millisecond flush interval for the worker's print buffering. A non-finite (NaN/Infinity) or negative value cannot be turned into a valid timer interval, so the transport rejects it with a `TypeError` before creating the session. Zero is allowed and means line-buffered (unbuffered) flushing.
Source
Thrown at crates/monty-js/ts/worker/transport.ts:40
Value as ComponentValue,
} from './component/monty.component.js'
import type { Dispatcher } from './host.js'
import { decodeValue, encodeValue } from './value.js'
type OnPrint = (stream: 'stdout' | 'stderr', text: string) => void
/**
* Encodes a print flush interval (seconds) as whole milliseconds for the WIT
* `u32`, mirroring `monty-pool`'s `flush_interval_ms`.
*
* The component encodes a `u32` as `val >>> 0`, which would silently wrap a
* negative or non-finite value into a huge interval, so reject those here.
* Zero is the line-buffering sentinel, so a positive interval never rounds
* down into it.
*/
function flushIntervalMs(interval: number): number {
if (!Number.isFinite(interval) || interval < 0) {
throw new TypeError(`invalid printFlushInterval: expected a non-negative number of seconds, got ${interval}`)
}
return interval === 0 ? 0 : Math.min(Math.max(Math.floor(interval * 1000), 1), 0xffffffff)
}
/** Resource limits mirrored from the napi pool; the transport enforces `maxSuspensions`. */
export interface ResourceLimits {
maxDurationSecs?: number
maxMemory?: number
gcInterval?: number
maxRecursionDepth?: number
maxSuspensions?: number
}
/** Session-creation options sent to the component worker. */
export interface WorkerSessionConfig {
scriptName?: string
limits?: ResourceLimits
typeCheck?: booleanView on GitHub (pinned to adc986b362)
Solutions
- Pass a finite, non-negative number of seconds (e.g. `0.05` for 50ms) or `0` for line-buffered behavior.
- Clamp/validate the value before constructing the config: `const interval = Number.isFinite(v) && v >= 0 ? v : 0.05`.
- If the value comes from user config, sanitize at load time so NaN/negatives become the documented default instead of reaching checkout().
- Omit `printFlushInterval` entirely to use the library default when you don't need custom flushing.
Example fix
// before
const session = await pool.checkout({ printFlushInterval: Number(process.env.FLUSH_S) }) // NaN if unset
// after
const raw = Number(process.env.FLUSH_S)
const printFlushInterval = Number.isFinite(raw) && raw >= 0 ? raw : 0.05
const session = await pool.checkout({ printFlushInterval }) Defensive patterns
Strategy: validation
Validate before calling
function sanitizeInterval(v: unknown): number {
const n = Number(v)
return Number.isFinite(n) && n >= 0 ? n : 0
} Type guard
function isFlushInterval(v: unknown): v is number {
return typeof v === 'number' && Number.isFinite(v) && v >= 0
} Try / catch
try {
session = await pool.checkout({ printFlushInterval: raw })
} catch (err) {
if (err instanceof TypeError && err.message.includes('printFlushInterval')) {
session = await pool.checkout({ printFlushInterval: 0.05 })
} else throw err
} Prevention
- Sanitize env/config numbers with Number.isFinite before use.
- Remember 0 means line-buffered, not 'disabled'.
- Express the value in seconds, not milliseconds.
- Validate all WorkerSessionConfig fields at config-load time.
When it happens
Trigger: Passing `printFlushInterval: NaN`, `Infinity`, `-1`, or any non-finite/negative number in the `WorkerSessionConfig` handed to `pool.checkout()` or `WorkerTransport.create()`.
Common situations: Computing the interval from a config parse that produced NaN (e.g. `Number(undefined)`), unit confusion (writing a negative 'disable' sentinel), or copying a config from another library that uses `Infinity` to mean 'never flush'.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Max input depth exceeded
- ClassInstance marker instanceId must be a uuid string
- ${field} must be 'all', undefined or a list/Set of names, go
- memoryUsageLimit must be a non-negative safe integer
- at least one OpenTelemetry component is required
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/377e1acc9c85ecf7.
Report an issue: GitHub.