{"record":{"id":"69ed8796939ccbcc","repo":"Zackriya-Solutions/meetily","slug":"no-transcripts-found-for-this-meeting","errorCode":null,"errorMessage":"No transcripts found for this meeting","messagePattern":"No transcripts found for this meeting","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/hooks/useTranscriptRecovery.ts","lineNumber":122,"sourceCode":"    }\n  }, []);\n\n  /**\n   * Recover a meeting from IndexedDB\n   */\n  const recoverMeeting = useCallback(async (meetingId: string): Promise<{ success: boolean; audioRecoveryStatus?: AudioRecoveryStatus | null; meetingId?: string }> => {\n    setIsRecovering(true);\n    try {\n      // 1. Load meeting metadata\n      const metadata = await indexedDBService.getMeetingMetadata(meetingId);\n      if (!metadata) {\n        throw new Error('Meeting metadata not found');\n      }\n\n      // 2. Load all transcripts\n      const transcripts = await loadMeetingTranscripts(meetingId);\n      if (transcripts.length === 0) {\n        throw new Error('No transcripts found for this meeting');\n      }\n\n      // 3. Check for folder path\n      let folderPath = metadata.folderPath;\n\n\n      if (!folderPath) {\n        // Try to get from backend (might exist if only app crashed, not system)\n        try {\n          folderPath = await invoke<string>('get_meeting_folder_path');\n        } catch (error) {\n          folderPath = undefined;\n        }\n      }\n\n      // 4. Attempt audio recovery if folder path exists\n      let audioRecoveryStatus: AudioRecoveryStatus | null = null;\n      if (folderPath) {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src/hooks/useTranscriptRecovery.ts#L104-L140","documentation":"In the same recoverMeeting flow, metadata loaded fine but loadMeetingTranscripts(meetingId) returned an empty array, so there is nothing to re-save, re-transcribe, or summarize. This is the classic partial-write signature: the app crashed or was killed after persisting meeting metadata but before flushing transcript chunks, or the transcript object store was cleared independently of metadata. Recovery of the audio file is still theoretically possible, but the current code aborts.","triggerScenarios":"App force-quit/killed mid-recording after the metadata record was written but before transcript chunks were saved; transcript flush only happens on stop and the crash preempted it; the transcripts store was cleared while the metadata store survived; transcripts written under a different key scheme than loadMeetingTranscripts reads.","commonSituations":"Power loss or OOM kill during long meetings, force-quitting from the tray/task manager mid-session, or an app upgrade that changed the transcript chunk keying without a migration.","solutions":["Inspect the transcripts object store for that meetingId's key range to confirm zero chunks were persisted.","If zero, recover from the audio file on disk (metadata.folderPath) and offer re-transcription instead of aborting.","Persist transcript chunks incrementally every few seconds during recording rather than one flush at stop.","Write a transcriptCount into the metadata record at save time so the UI can warn about partial data before recovery is attempted."],"exampleFix":"// before\nconst transcripts = await loadMeetingTranscripts(meetingId);\nif (transcripts.length === 0) {\n  throw new Error('No transcripts found for this meeting');\n}\n\n// after — degrade to audio-only recovery when the audio still exists\nconst transcripts = await loadMeetingTranscripts(meetingId);\nif (transcripts.length === 0 && metadata.folderPath) {\n  toast.info('No saved transcripts — recovering from the audio file');\n  return {\n    success: true,\n    audioRecoveryStatus: await recoverAudioOnly(metadata.folderPath),\n    meetingId,\n  };\n}\nif (transcripts.length === 0) {\n  throw new Error('No transcripts found for this meeting');\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await recoverMeeting(meetingId);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('No transcripts found')) {\n    // degrade gracefully: recover audio only, offer re-transcription from the saved file\n    return { success: true, audioRecoveryStatus: 'audio-only', meetingId };\n  }\n  throw e;\n}","preventionTips":["Persist transcript chunks incrementally every few seconds during recording, not in one flush at stop.","Write a transcriptCount into meeting metadata so partial meetings are detectable before recovery is attempted.","Exercise recovery paths in CI by force-killing the app mid-recording."],"tags":["indexeddb","recovery","transcripts","partial-write"],"backgroundTag":"partial-write-data-loss","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}