{"record":{"id":"430dfdbc2121ace6","repo":"stablyai/orca","slug":"open-the-review-file-before-sending","errorCode":null,"errorMessage":"open the review file before sending","messagePattern":"open the review file before sending","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/main/ipc/diagnostics.ts","lineNumber":119,"sourceCode":"}\n\nfunction getPendingBundleForUpload(bundleSubmissionId: unknown): {\n  readonly bundle: CollectedBundle\n  readonly payload: string\n} {\n  if (\n    typeof bundleSubmissionId !== 'string' ||\n    !/^[A-Za-z0-9_-]{16,64}$/.test(bundleSubmissionId)\n  ) {\n    throw new Error('bundleSubmissionId has invalid format')\n  }\n  prunePendingBundles()\n  const pending = pendingBundles.get(bundleSubmissionId)\n  if (!pending) {\n    throw new Error('review file has expired; create a new one before sending')\n  }\n  if (!pending.previewOpened) {\n    throw new Error('open the review file before sending')\n  }\n  // Why: the preview file is user-editable once opened in the OS. Upload only\n  // the redacted bytes main collected and retained before preview.\n  return { bundle: pending.bundle, payload: pending.bundle.payload }\n}\n\nfunction getPendingPreviewFilePath(bundleSubmissionId: unknown): string {\n  if (\n    typeof bundleSubmissionId !== 'string' ||\n    !/^[A-Za-z0-9_-]{16,64}$/.test(bundleSubmissionId)\n  ) {\n    throw new Error('bundleSubmissionId has invalid format')\n  }\n  prunePendingBundles()\n  const pending = pendingBundles.get(bundleSubmissionId)\n  if (!pending) {\n    throw new Error('review file has expired; create a new one before opening')\n  }","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/diagnostics.ts#L101-L137","documentation":"Thrown by getPendingBundleForUpload when the pending bundle exists but its previewOpened flag is false. The upload path is only allowed after the user has opened the review file preview — both as a UX gate (the user should review what is sent) and because the uploaded payload is the redacted bytes retained before the preview file became user-editable.","triggerScenarios":"Calling send/upload on a bundle whose preview was never opened. The bundle is still pending (not expired), but the preview-open step was skipped — e.g. the user clicked send directly from a different UI flow without opening the preview first.","commonSituations":"User attempts to send from a list/action without first opening the preview; a buggy flow wires the send button before the open action; the preview-open IPC failed silently so the flag was never set.","solutions":["Open the review file preview first (the open-preview IPC), then send.","If the preview-open call failed, retry it and confirm the preview window appeared before sending.","Verify the renderer sets previewOpened=true only after a successful open confirmation."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isPreviewOpened(id: string): boolean {\n  return pendingBundles.get(id)?.previewOpened === true\n}","typeGuard":"function isBundlePreviewOpened(entry: unknown): boolean {\n  return typeof entry === 'object' && entry !== null && (entry as any).previewOpened === true\n}","tryCatchPattern":"try {\n  return getPendingBundleForUpload(id)\n} catch (error) {\n  if (error instanceof Error && /open the review file before sending/.test(error.message)) {\n    await openPreview(id)\n    return getPendingBundleForUpload(id)\n  }\n  throw error\n}","preventionTips":["Always trigger the open-preview IPC before enabling the send action.","Disable the send button in the UI until previewOpened is true.","Confirm the preview window opened successfully before marking previewOpened."],"tags":["diagnostics","review-file","ipc","workflow","ux-gate"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}