moeru-ai/airi · error · Error
mutexAcquireTimeout must be a positive finite number
Error message
mutexAcquireTimeout must be a positive finite number
What it means
initScreenCaptureForMain validates the mutexAcquireTimeout option (default 5000 ms) up front: it must be > 0, finite, and not NaN, because it is passed to withTimeout(new Mutex(), ...) to bound source-mutex acquisition. Any invalid custom value throws immediately during Electron main-process setup.
Solutions
- Pass a positive finite millisecond value, or omit the option to keep the 5000 ms default
- Sanitize env/config-derived numbers: Number.isFinite(t) && t > 0 before forwarding
- If you intended 'no timeout', keep a large finite value instead of Infinity — the API deliberately rejects it
Example fix
// before
initScreenCaptureForMain({ mutexAcquireTimeout: Number(process.env.SCREEN_CAP_TIMEOUT) }) // NaN when unset
// after
const t = Number(process.env.SCREEN_CAP_TIMEOUT)
initScreenCaptureForMain({ mutexAcquireTimeout: Number.isFinite(t) && t > 0 ? t : 5000 }) Defensive patterns
Strategy: validation
Validate before calling
const t = options.mutexAcquireTimeout ?? 5000
if (!(typeof t === 'number' && t > 0 && Number.isFinite(t)))
throw new Error('mutexAcquireTimeout must be a positive finite number (ms)')
await initScreenCaptureForMain({ ...options, mutexAcquireTimeout: t }) Type guard
function isPositiveFinite(v: unknown): v is number {
return typeof v === 'number' && v > 0 && Number.isFinite(v)
} Prevention
- Sanitize env/config-derived numbers with Number.isFinite before forwarding
- Document that 0/Infinity mean 'reject', not 'disable the timeout'
- Omit the option to accept the 5000 ms default
When it happens
Trigger: Passing mutexAcquireTimeout: 0, a negative number, Infinity, or NaN — classically Number(undefinedEnvVar) or parseInt of an unset/blank config value.
Common situations: Timeout sourced from an environment variable or config file that is unset on another machine; a 'disable timeout' attempt passing 0; copy-pasted config with an empty string coerced to 0.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- initScreenCaptureForMain must be called before calling…
- initScreenCaptureForMain should only be called once
- initScreenCaptureForWindow should only be called once per…
- The AR-HMM iteration count must be a positive integer.
- The AR-HMM state count must be an integer greater than one.
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/98fbd1310ae6a0fa.
Report an issue: GitHub.
Appendix: source
Thrown at packages/electron-screen-capture/src/main/index.ts:113
let screenCaptureSourceMutexHandle: string | undefined
let setSourceMutexTimeoutHandle: NodeJS.Timeout | undefined
export function initScreenCaptureForMain(options: InitMainOptions = {}): void {
const {
forceCoreAudioTap = false,
mutexAcquireTimeout = 5000,
} = options
let log = useLogg('screen-capture').useGlobalConfig()
if (options?.loggerOptions?.logLevel) {
log = log.withLogLevelString((options?.loggerOptions?.logLevel ?? 'info') as LogLevelString)
}
if (options?.loggerOptions?.format) {
log = log.withFormat((options?.loggerOptions?.format ?? 'plain') as Format)
}
if (mutexAcquireTimeout <= 0 || !Number.isFinite(mutexAcquireTimeout) || Number.isNaN(mutexAcquireTimeout)) {
throw new Error('mutexAcquireTimeout must be a positive finite number')
}
if (initMainCalled) {
log.warn('initScreenCaptureForMain should only be called once')
return
}
initMainCalled = true
setSourceMutex = withTimeout(new Mutex(), mutexAcquireTimeout)
// Get other enabled features from the command line.
const otherEnabledFeatures = app.commandLine.getSwitchValue(featureSwitchKey)?.split(',')
// Remove the switch if it exists.
if (app.commandLine.hasSwitch(featureSwitchKey)) {
app.commandLine.removeSwitch(featureSwitchKey)
}
// Add the feature flags to the command line with any other user-enabled features concatenated.View on GitHub (pinned to 677329427f)