stablyai/orca · error · Error

Failed to send notes

Error message

Failed to send notes

What it means

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.

Source

Thrown at mobile/src/session/use-mobile-diff-review-send-actions.ts:81

      const next = markMobileDiffCommentsSent(
        screenState.comments,
        new Set(comments.map((comment) => comment.id)),
        Date.now()
      )
      await saveCommentsAndReviewState(next, screenState.reviewState)
    },
    [saveCommentsAndReviewState, screenState]
  )

  const sendPromptToTerminal = useCallback(
    async (terminal: string, comments: readonly DiffComment[]) => {
      if (!client || connState !== 'connected') {
        throw new Error('Waiting for desktop...')
      }
      // Marked by terminal handle, not by surface, so a paste orphaned here by native
      // chat would ride along with these notes (#10228). Diff review carries no device token.
      if (!(await healMobileNativeChatStaleInput({ client, terminal, deviceToken: null }))) {
        throw new Error('Failed to send notes')
      }
      const response = await client.sendRequest('terminal.send', {
        terminal,
        text: formatMobileDiffReviewPrompt(comments),
        enter: true
      })
      if (!response.ok) {
        throw new Error(response.error?.message || 'Failed to send notes')
      }
      if (!readMobileReviewTerminalSendAccepted(response.result)) {
        throw new Error('Terminal input is locked')
      }
      await markNotesSent(comments)
      triggerSuccess()
      setActionError('Review notes sent')
      setSendSheet(null)
    },
    [client, connState, markNotesSent, setActionError, setSendSheet]

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Retry the send (heal is idempotent and the marker persists).
  2. Manually clear the terminal input line on the host.
  3. Create a fresh terminal for the notes.
  4. Reconnect if the heal failed on transport.

Example fix

// before
if (!(await healMobileNativeChatStaleInput({ client, terminal, deviceToken: null }))) {
  throw new Error('Failed to send notes')
}
// after - fall back to a fresh terminal instead of failing
if (!(await healMobileNativeChatStaleInput({ client, terminal, deviceToken: null }))) {
  const fresh = await createFreshTerminal(client, worktreeId)
  return sendPromptToTerminal(fresh, comments)
}
Defensive patterns

Strategy: retry

Validate before calling

if (isMobileNativeChatInputStale(terminal)) {
  setActionError('Clear the pending image on this terminal first')
  return
}

Try / catch

try {
  await sendPromptToTerminal(terminal, comments)
} catch (err) {
  if (/Failed to send notes/.test(err instanceof Error ? err.message : '')) {
    return createTerminalAndSend(comments)
  }
  throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/3ea6f73c6fb302af. Report an issue: GitHub.