{"record":{"id":"4f2307f22efc7922","repo":"Zackriya-Solutions/meetily","slug":"update-check-already-in-progress","errorCode":null,"errorMessage":"Update check already in progress","messagePattern":"Update check already in progress","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"info","filePath":"frontend/src/services/updateService.ts","lineNumber":44,"sourceCode":"\n/**\n * Update Service\n * Singleton service for managing app updates\n */\nexport class UpdateService {\n  private updateCheckInProgress = false;\n  private lastCheckTime: number | null = null;\n  private readonly CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours\n\n  /**\n   * Check for available updates\n   * @param force Force check even if recently checked\n   * @returns Promise with update information\n   */\n  async checkForUpdates(force = false): Promise<UpdateInfo> {\n    // Prevent concurrent update checks\n    if (this.updateCheckInProgress) {\n      throw new Error('Update check already in progress');\n    }\n\n    // Skip if checked recently (unless forced)\n    if (!force && this.lastCheckTime) {\n      const timeSinceLastCheck = Date.now() - this.lastCheckTime;\n      if (timeSinceLastCheck < this.CHECK_INTERVAL_MS) {\n        console.log('Skipping update check - checked recently');\n        return {\n          available: false,\n          currentVersion: await getVersion(),\n        };\n      }\n    }\n\n    this.updateCheckInProgress = true;\n    this.lastCheckTime = Date.now();\n\n    try {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src/services/updateService.ts#L26-L62","documentation":"UpdateService.checkForUpdates uses the updateCheckInProgress boolean to prevent overlapping network checks and throws this guard error on re-entry — it is not a network failure. It fires when a second caller invokes checkForUpdates while the first await on the update endpoint is still pending. The guard throws rather than returning the in-flight promise, so every caller must either prevent the second call or catch this exact message.","triggerScenarios":"App-startup automatic check racing a manual 'Check for updates' button click; React StrictMode double-invoking the effect that calls checkForUpdates in development; two components mounting and both calling it on load.","commonSituations":"React 18 StrictMode double-mount in dev, a settings page and a startup hook both polling, or a user double-clicking the update button before it disables itself.","solutions":["Short-circuit callers: check the in-progress flag (expose a getter) or disable the button while a check runs.","In React StrictMode dev runs, guard the mount-time call with a ref so the double-mount doesn't issue two checks.","Refactor checkForUpdates to memoize and return the in-flight promise instead of throwing (see exampleFix) — the cleanest fix.","Catch this specific message in callers and treat it as a no-op, not an error toast."],"exampleFix":"// before\nif (this.updateCheckInProgress) {\n  throw new Error('Update check already in progress');\n}\n\n// after — share the in-flight promise instead of throwing\nprivate inFlight: Promise<UpdateInfo> | null = null;\nasync checkForUpdates(force = false): Promise<UpdateInfo> {\n  if (!force && this.inFlight) return this.inFlight;\n  const p = this.doCheck(force).finally(() => { this.inFlight = null; });\n  this.inFlight = p;\n  return p;\n}","handlingStrategy":"validation","validationCode":"// expose state on the service\nget isChecking() { return this.updateCheckInProgress; }\n\n// caller\nif (updateService.isChecking) return; // a check is already running\nawait updateService.checkForUpdates(true);","typeGuard":null,"tryCatchPattern":"try {\n  await updateService.checkForUpdates(true);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Update check already in progress') return; // benign re-entry\n  throw e;\n}","preventionTips":["Disable the 'Check for updates' button while a check runs.","In React StrictMode/dev, guard mount-time calls with a ref so double effects don't double-check.","Prefer returning the in-flight promise over throwing on re-entry."],"tags":["updates","concurrency","singleton-guard"],"backgroundTag":"duplicate-request-guard","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}