{"record":{"id":"98fbd1310ae6a0fa","repo":"moeru-ai/airi","slug":"mutexacquiretimeout-must-be-a-positive-finite-numb","errorCode":null,"errorMessage":"mutexAcquireTimeout must be a positive finite number","messagePattern":"mutexAcquireTimeout must be a positive finite number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/electron-screen-capture/src/main/index.ts","lineNumber":113,"sourceCode":"let screenCaptureSourceMutexHandle: string | undefined\nlet setSourceMutexTimeoutHandle: NodeJS.Timeout | undefined\n\nexport function initScreenCaptureForMain(options: InitMainOptions = {}): void {\n  const {\n    forceCoreAudioTap = false,\n    mutexAcquireTimeout = 5000,\n  } = options\n\n  let log = useLogg('screen-capture').useGlobalConfig()\n  if (options?.loggerOptions?.logLevel) {\n    log = log.withLogLevelString((options?.loggerOptions?.logLevel ?? 'info') as LogLevelString)\n  }\n  if (options?.loggerOptions?.format) {\n    log = log.withFormat((options?.loggerOptions?.format ?? 'plain') as Format)\n  }\n\n  if (mutexAcquireTimeout <= 0 || !Number.isFinite(mutexAcquireTimeout) || Number.isNaN(mutexAcquireTimeout)) {\n    throw new Error('mutexAcquireTimeout must be a positive finite number')\n  }\n\n  if (initMainCalled) {\n    log.warn('initScreenCaptureForMain should only be called once')\n    return\n  }\n  initMainCalled = true\n  setSourceMutex = withTimeout(new Mutex(), mutexAcquireTimeout)\n\n  // Get other enabled features from the command line.\n  const otherEnabledFeatures = app.commandLine.getSwitchValue(featureSwitchKey)?.split(',')\n\n  // Remove the switch if it exists.\n  if (app.commandLine.hasSwitch(featureSwitchKey)) {\n    app.commandLine.removeSwitch(featureSwitchKey)\n  }\n\n  // Add the feature flags to the command line with any other user-enabled features concatenated.","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/electron-screen-capture/src/main/index.ts#L95-L131","documentation":"Thrown by initScreenCaptureForMain() when options.mutexAcquireTimeout is a number that is <= 0, not finite (Infinity/-Infinity), or NaN. The value is used to wrap the source-selection Mutex with withTimeout, so a non-positive or unbounded timeout would make acquisition semantics meaningless.","triggerScenarios":"Passing mutexAcquireTimeout: 0, a negative number, Infinity, or NaN in InitMainOptions; passing a value read from env/JSON config without coercion that ends up as NaN.","commonSituations":"Config file with mutexAcquireTimeout: 0 intending 'no wait'; env var parsed with Number('') producing 0; JSON config with a string that Number()-coerces to NaN; copy-paste of a default that was later changed.","solutions":["Omit the option to accept the 5000ms default, or pass a positive finite number such as 5000.","Coerce and validate config-sourced values: const t = Number(raw); if (!(t > 0 && Number.isFinite(t))) use default.","Reject non-numeric config at the boundary instead of forwarding it to initScreenCaptureForMain."],"exampleFix":"// before\ninitScreenCaptureForMain({ mutexAcquireTimeout: Number(process.env.SCREENCAP_TIMEOUT) })\n// after\nconst raw = Number(process.env.SCREENCAP_TIMEOUT)\ninitScreenCaptureForMain({ mutexAcquireTimeout: Number.isFinite(raw) && raw > 0 ? raw : 5000 })","handlingStrategy":"validation","validationCode":"function resolveMutexTimeout(raw: unknown): number {\n  const n = typeof raw === 'number' ? raw : Number(raw)\n  if (!(Number.isFinite(n) && n > 0)) return 5000 // default\n  return n\n}\n\ninitScreenCaptureForMain({ mutexAcquireTimeout: resolveMutexTimeout(configValue) })","typeGuard":"function isPositiveFinite(n: unknown): n is number {\n  return typeof n === 'number' && Number.isFinite(n) && n > 0\n}","tryCatchPattern":null,"preventionTips":["Coerce env/config timeouts with a positive-finite guard and a default.","Document the unit (milliseconds) at the config boundary.","Reject non-numeric config values early rather than forwarding."],"tags":["electron","screen-capture","config-validation","mutex"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}