{"record":{"id":"b674bd61ccc952ab","repo":"usebruno/bruno","slug":"watcher-or-mainwindow-not-available","errorCode":null,"errorMessage":"Watcher or mainWindow not available","messagePattern":"Watcher or mainWindow not available","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-electron/src/ipc/collection.js","lineNumber":2345,"sourceCode":"      await writeFile(path.join(tempDirectoryPath, 'opencollection.yml'), content);\n\n      const metadata = {\n        workspaceUid,\n        workspacePath,\n        type: 'scratch'\n      };\n      fs.writeFileSync(path.join(tempDirectoryPath, 'metadata.json'), JSON.stringify(metadata));\n\n      return tempDirectoryPath;\n    } catch (error) {\n      console.error('Error mounting workspace scratch collection:', error);\n      throw error;\n    }\n  });\n\n  ipcMain.handle('renderer:add-collection-watcher', async (event, { collectionPath, collectionUid, brunoConfig }) => {\n    if (!watcher || !mainWindow) {\n      throw new Error('Watcher or mainWindow not available');\n    }\n\n    try {\n      const { size, filesCount, maxFileSize } = await getCollectionStats(collectionPath);\n\n      const shouldLoadCollectionAsync\n        = (size > MAX_COLLECTION_SIZE_IN_MB)\n          || (filesCount > MAX_COLLECTION_FILES_COUNT)\n          || (maxFileSize > MAX_SINGLE_FILE_SIZE_IN_COLLECTION_IN_MB);\n\n      watcher.addWatcher(mainWindow, collectionPath, collectionUid, brunoConfig, false, shouldLoadCollectionAsync);\n\n      return { success: true };\n    } catch (error) {\n      console.error('Error adding collection watcher:', error);\n      throw error;\n    }\n  });","sourceCodeStart":2327,"sourceCodeEnd":2363,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-electron/src/ipc/collection.js#L2327-L2363","documentation":"The renderer:add-collection-watcher handler requires both the module-level `watcher` (file system watcher instance) and `mainWindow` (Electron BrowserWindow) to be initialized before it can wire up notifications. The check runs before any try/catch, so the error propagates directly to the renderer.","triggerScenarios":"Calling renderer:add-collection-watcher before app 'ready' has fired, before mainWindow is created, after the watcher has been disposed, or during shutdown when mainWindow is null.","commonSituations":"Startup race where the renderer fires the IPC during its mount before the main process finished wiring the watcher; shutdown sequence where the window was closed but the renderer is still alive; watcher initialization failed silently at boot.","solutions":["Gate the renderer call on the main-process 'ready' event and on a 'mainWindow-ready' IPC handshake.","Ensure watcher is constructed in app.whenReady() before any window loads.","On re-open after close, re-create the watcher rather than reusing a disposed instance.","Log watcher/mainWindow init failures at boot so silent null states surface."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// renderer-side: only call after the main process signals readiness\nif (!window.__BRUNO_MAIN_READY__) {\n  console.warn('Deferring add-collection-watcher: main process not ready');\n  return;\n}\nipcRenderer.invoke('renderer:add-collection-watcher', { collectionPath, collectionUid, brunoConfig });","typeGuard":null,"tryCatchPattern":"try {\n  await ipcRenderer.invoke('renderer:add-collection-watcher', payload);\n} catch (err) {\n  if (/Watcher or mainWindow not available/.test(err.message)) {\n    // back off and retry once after app-ready, do not spam\n  } else {\n    throw err;\n  }\n}","preventionTips":["Construct the watcher inside app.whenReady() and expose a ready handshake to the renderer.","Tear down IPC callers before nulling mainWindow during shutdown.","Log watcher initialization failures at boot so silent null states surface early."],"tags":["ipc","watcher","electron","lifecycle","race-condition","startup"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}