{"record":{"id":"3ea6f73c6fb302af","repo":"stablyai/orca","slug":"failed-to-send-notes-3ea6f7","errorCode":null,"errorMessage":"Failed to send notes","messagePattern":"Failed to send notes","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mobile/src/session/use-mobile-diff-review-send-actions.ts","lineNumber":81,"sourceCode":"      const next = markMobileDiffCommentsSent(\n        screenState.comments,\n        new Set(comments.map((comment) => comment.id)),\n        Date.now()\n      )\n      await saveCommentsAndReviewState(next, screenState.reviewState)\n    },\n    [saveCommentsAndReviewState, screenState]\n  )\n\n  const sendPromptToTerminal = useCallback(\n    async (terminal: string, comments: readonly DiffComment[]) => {\n      if (!client || connState !== 'connected') {\n        throw new Error('Waiting for desktop...')\n      }\n      // Marked by terminal handle, not by surface, so a paste orphaned here by native\n      // chat would ride along with these notes (#10228). Diff review carries no device token.\n      if (!(await healMobileNativeChatStaleInput({ client, terminal, deviceToken: null }))) {\n        throw new Error('Failed to send notes')\n      }\n      const response = await client.sendRequest('terminal.send', {\n        terminal,\n        text: formatMobileDiffReviewPrompt(comments),\n        enter: true\n      })\n      if (!response.ok) {\n        throw new Error(response.error?.message || 'Failed to send notes')\n      }\n      if (!readMobileReviewTerminalSendAccepted(response.result)) {\n        throw new Error('Terminal input is locked')\n      }\n      await markNotesSent(comments)\n      triggerSuccess()\n      setActionError('Review notes sent')\n      setSendSheet(null)\n    },\n    [client, connState, markNotesSent, setActionError, setSendSheet]","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/session/use-mobile-diff-review-send-actions.ts#L63-L99","documentation":"Thrown when `healMobileNativeChatStaleInput` returned false before sending notes. The heal clears a leftover bracketed image-paste sitting on the terminal's unsubmitted input line (#10228); if that clear fails (or threw), the notes are NOT sent to avoid gluing them onto the stale paste. The stale marker stays set for the next attempt.","triggerScenarios":"The terminal was previously marked stale (an image paste was left unsubmitted), and the heal's pasteMobileNativeChatImagePaths clear either threw or returned false - the clear terminal.send was rejected, input was locked, or the transport failed.","commonSituations":"A prior native-chat image paste did not submit; the clear write hit an input-locked terminal; relay cutover during the heal; the host rejected the empty-paste clear.","solutions":["Retry the send (heal is idempotent and the marker persists).","Manually clear the terminal input line on the host.","Create a fresh terminal for the notes.","Reconnect if the heal failed on transport."],"exampleFix":"// before\nif (!(await healMobileNativeChatStaleInput({ client, terminal, deviceToken: null }))) {\n  throw new Error('Failed to send notes')\n}\n// after - fall back to a fresh terminal instead of failing\nif (!(await healMobileNativeChatStaleInput({ client, terminal, deviceToken: null }))) {\n  const fresh = await createFreshTerminal(client, worktreeId)\n  return sendPromptToTerminal(fresh, comments)\n}","handlingStrategy":"retry","validationCode":"if (isMobileNativeChatInputStale(terminal)) {\n  setActionError('Clear the pending image on this terminal first')\n  return\n}","typeGuard":null,"tryCatchPattern":"try {\n  await sendPromptToTerminal(terminal, comments)\n} catch (err) {\n  if (/Failed to send notes/.test(err instanceof Error ? err.message : '')) {\n    return createTerminalAndSend(comments)\n  }\n  throw err\n}","preventionTips":["Submit or discard native-chat image pastes before opening the send sheet.","Prefer freshly-created terminals for note sends.","Retry heal once on transient transport errors."],"tags":["stale-input","heal","send-notes","diff-review","mobile"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}