stablyai/orca · error · Error

Failed to save review notes

Error message

Failed to save review notes

What it means

Thrown in persistDiffComments() when the worktree.set RPC returns a failure response (ok: false) AND the failure has no error.message. This is the fallback error string when the server-side error message is empty or missing. The RPC was sent and a response received, but the server rejected the diff comment save without a descriptive error.

Source

Thrown at mobile/app/h/[hostId]/session/[worktreeId].tsx:1953

      return
    }
    const result = (response as RpcSuccess).result as {
      worktree?: { diffComments?: unknown }
    }
    setDiffComments(normalizeMobileDiffComments(result.worktree?.diffComments, worktreeId))
  }, [client, connState, worktreeId, isFloatingWorkspaceRoute])

  const persistDiffComments = useCallback(
    async (comments: readonly DiffComment[]): Promise<void> => {
      if (!client || connState !== 'connected') {
        throw new Error('Waiting for desktop...')
      }
      const response = await client.sendRequest('worktree.set', {
        worktree: `id:${worktreeId}`,
        diffComments: comments
      })
      if (!response.ok) {
        throw new Error((response as RpcFailure).error.message || 'Failed to save review notes')
      }
    },
    [client, connState, worktreeId]
  )

  useEffect(() => {
    void loadDiffComments()
  }, [loadDiffComments])

  const addDiffCommentForFile = useCallback(
    async (filePath: string, lineNumber: number, body: string): Promise<boolean> => {
      if (diffCommentBusy) {
        return false
      }
      const nextId = `mobile-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`
      const result = addMobileDiffComment(diffCommentsRef.current, {
        id: nextId,
        worktreeId,

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Check the desktop host logs for the actual worktree.set rejection reason.
  2. Verify the diffComments payload matches the schema expected by the desktop host version.
  3. If error.message is empty, log the full failure object (code, details) to diagnose the server-side rejection.
  4. Ensure mutation ownership is captured before the worktree.set call.

Example fix

// before: empty server message gives generic error
throw new Error((response as RpcFailure).error.message || 'Failed to save review notes')

// after: include error code for diagnosability
const failure = response as RpcFailure
throw new Error(
  failure.error.message ||
  `Failed to save review notes (code: ${failure.error.code ?? 'unknown'})`
)
Defensive patterns

Strategy: try-catch

Validate before calling

function buildPersistErrorMessage(response) {
  if (response.ok) return null
  const failure = response as RpcFailure
  return failure.error.message || `Failed to save review notes (code: ${failure.error.code ?? 'unknown'})`
}

Type guard

function isRpcFailureWithMessage(response) {
  return !response.ok && typeof response.error?.message === 'string' &&
    response.error.message.length > 0
}

Try / catch

try {
  await persistDiffComments(comments)
} catch (err) {
  if (err.message === 'Failed to save review notes') {
    // Server returned an error with no message — log the full failure for diagnosis
    console.error('worktree.set failed with no message — check host logs')
  }
  showToast(err.message, 1800)
}

Prevention

When it happens

Trigger: client.sendRequest('worktree.set', { worktree, diffComments }) returns ok:false with error.message being empty/undefined. Caused by: the desktop host rejecting the diff comments payload (schema mismatch, worktree not found, ownership conflict) but returning an error with no message field.

Common situations: A version skew between mobile client and desktop host where the diffComments schema changed; a worktree that was removed server-side; a mutation ownership conflict where another client holds the lock; a server bug returning an error object without a message.

Related errors


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