{"record":{"id":"e0d6a782abb12a28","repo":"stablyai/orca","slug":"sending-diagnostics-is-disabled","errorCode":null,"errorMessage":"sending diagnostics is disabled","messagePattern":"sending diagnostics is disabled","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/main/ipc/diagnostics.ts","lineNumber":253,"sourceCode":"        orcaChannel: resolveDiagnosticOrcaChannel(),\n        ...(lookbackMinutes !== undefined ? { lookbackMinutes } : {})\n      })\n      rememberBundle(bundle)\n      return toBundlePreview(bundle)\n    }\n  )\n\n  ipcMain.handle(\n    'diagnostics:uploadBundle',\n    async (_event, bundleSubmissionId: unknown): Promise<UploadBundleIpcResult> => {\n      // Why: the renderer is in the threat model. Upload only a payload main\n      // collected and retained for preview, never renderer-supplied bytes.\n      const pendingForConfirmation = getPendingBundleForUpload(bundleSubmissionId)\n      // Consent gate: main is the consent enforcement boundary; the\n      // renderer-side button-hide is UX, not security. Re-check here in case\n      // the user toggled the setting off between collect and upload.\n      if (!getDiagnosticsStatus().bundleEnabled) {\n        throw new Error('sending diagnostics is disabled')\n      }\n      const confirmed = await confirmBundleUpload(pendingForConfirmation.bundle)\n      if (!confirmed) {\n        return { canceled: true }\n      }\n      // Why: the preview can be discarded or diagnostics can be disabled\n      // while the native confirmation dialog is open.\n      const { bundle, payload } = getPendingBundleForUpload(bundleSubmissionId)\n      if (!getDiagnosticsStatus().bundleEnabled) {\n        throw new Error('sending diagnostics is disabled')\n      }\n      const tokenEndpoint = resolveDiagnosticTokenEndpoint()\n      if (!tokenEndpoint) {\n        throw new Error('sending diagnostics is not configured for this build')\n      }\n      const result = await uploadDiagnosticBundle({\n        tokenEndpoint,\n        payload,","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/diagnostics.ts#L235-L271","documentation":"First of two consent re-checks in the `diagnostics:uploadBundle` IPC handler, fired before the native confirmation dialog. Main re-reads `getDiagnosticsStatus()` because the renderer is in the threat model and the user may have toggled the Privacy setting off in the window between collect and upload. Throwing here guarantees consent is current at the moment of upload.","triggerScenarios":"Calling `ipcRenderer.invoke('diagnostics:uploadBundle', bundleSubmissionId)` after the user disabled bundle collection in Settings -> Privacy sometime after the bundle was collected but before upload began.","commonSituations":"User collected a bundle, changed their mind in Privacy settings, then clicked upload; automated flow that collected then waited while the setting was flipped; long pause between collect and upload during which consent was revoked.","solutions":["Before calling upload, re-check `diagnostics:getStatus` and abort the upload flow if `bundleEnabled` is false.","If the user meant to upload, re-enable diagnostic-bundle collection in Settings -> Privacy, then collect a fresh bundle and upload it.","Have the renderer treat a disabled status as a hard stop and discard any retained preview it holds."],"exampleFix":"// before\nawait ipcRenderer.invoke('diagnostics:uploadBundle', submissionId)\n\n// after\nconst status = await ipcRenderer.invoke('diagnostics:getStatus')\nif (!status.bundleEnabled) {\n  // consent revoked since collect; abort and tell the user\n  return\n}\nawait ipcRenderer.invoke('diagnostics:uploadBundle', submissionId)","handlingStrategy":"validation","validationCode":"// Re-check consent right before upload; it may have changed since collect.\nconst status = await ipcRenderer.invoke('diagnostics:getStatus')\nif (!status.bundleEnabled) {\n  // consent revoked since collect; abort the upload flow\n  return\n}\nawait ipcRenderer.invoke('diagnostics:uploadBundle', submissionId)","typeGuard":"function bundleStillEnabled(s: unknown): boolean {\n  return typeof s === 'object' && s !== null && (s as any).bundleEnabled === true\n}","tryCatchPattern":"try {\n  await ipcRenderer.invoke('diagnostics:uploadBundle', submissionId)\n} catch (e) {\n  if (e instanceof Error && e.message === 'sending diagnostics is disabled') {\n    showConsentRevokedNotice()\n    return\n  }\n  throw e\n}","preventionTips":["Never assume consent held at collect time still holds at upload time.","Re-read status synchronously before each consent-gated network action.","Discard retained preview handles when consent flips off, to avoid retrying a now-forbidden upload."],"tags":["diagnostics","consent","privacy","ipc","toctou","security-boundary"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}