From 6e1f908a7999ca95f264c5b4eed1f9c736768ec2 Mon Sep 17 00:00:00 2001 From: Jira Coding Agent Date: Tue, 30 Jun 2026 04:20:34 +0000 Subject: [PATCH] fix(rovodev): stop sending AxiosError to Sentry in feedback submission Replace RovoDevTelemetryProvider.logError() with Logger.warn() in RovoDevFeedbackManager.submitFeedback to prevent feedback submission failures (network errors, non-2xx responses) from being reported to Sentry and triggering SLO errors. These failures are non-critical and expected in transient failure scenarios. Co-authored-by: Evan Cook --- CHANGELOG.md | 6 ++ src/rovo-dev/rovoDevFeedbackManager.test.ts | 61 +++++++++++++++++---- src/rovo-dev/rovoDevFeedbackManager.ts | 11 +++- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69337d08a..d065af833 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ### [Report an Issue](https://github.com/atlassian/atlascode/issues) +## What's new in 4.0.32 + +### Bug Fixes + +- **RovoDev**: Fixed `AxiosError` in `RovoDevFeedbackManager.submitFeedback` being sent to Sentry and triggering SLO errors. Feedback submission failures (network errors, non-2xx responses) are now logged as warnings instead, since they are non-critical and expected in transient failure scenarios. + ## What's new in 4.0.31 ### Bug Fixes diff --git a/src/rovo-dev/rovoDevFeedbackManager.test.ts b/src/rovo-dev/rovoDevFeedbackManager.test.ts index 69ebe1e0e..003098d92 100644 --- a/src/rovo-dev/rovoDevFeedbackManager.test.ts +++ b/src/rovo-dev/rovoDevFeedbackManager.test.ts @@ -12,23 +12,18 @@ jest.mock('./api/extensionApi', () => ({ ExtensionApi: jest.fn().mockImplementation(() => mockExtensionApiInstance), })); -jest.mock('./rovoDevTelemetryProvider', () => ({ - RovoDevTelemetryProvider: { - logError: jest.fn(), - }, -})); - jest.mock('lodash', () => ({ ...jest.requireActual('lodash'), truncate: jest.fn((str, options) => str), })); +import { AxiosError } from 'axios'; +import { Logger } from 'src/logger'; import { UserInfo } from 'src/rovo-dev/api/extensionApiTypes'; import * as vscode from 'vscode'; import { getAxiosInstance } from './api/extensionApi'; import { RovoDevFeedbackManager } from './rovoDevFeedbackManager'; -import { RovoDevTelemetryProvider } from './rovoDevTelemetryProvider'; describe('RovoDevFeedbackManager', () => { const mockTransport = jest.fn(); @@ -158,8 +153,50 @@ describe('RovoDevFeedbackManager', () => { expect(vscode.window.showErrorMessage).not.toHaveBeenCalled(); }); - it('should handle submission error and show error message', async () => { - const error = new Error('Network error'); + it('should handle AxiosError with response status and log warning without sending to Sentry', async () => { + const axiosError = new AxiosError('Request failed with status code 500', '500', undefined, undefined, { + status: 500, + statusText: 'Internal Server Error', + headers: {}, + config: {} as any, + data: {}, + }); + mockTransport.mockRejectedValue(axiosError); + + const feedback = { + feedbackType: 'general' as const, + feedbackMessage: 'Test feedback', + canContact: false, + }; + + await RovoDevFeedbackManager.submitFeedback(feedback); + + expect(Logger.warn).toHaveBeenCalledWith(expect.stringContaining('HTTP 500')); + expect(vscode.window.showErrorMessage).toHaveBeenCalledWith( + 'There was an error submitting your feedback. Please try again later.', + ); + }); + + it('should handle AxiosError without response (network error) and log warning', async () => { + const axiosError = new AxiosError('Network Error', 'ERR_NETWORK'); + mockTransport.mockRejectedValue(axiosError); + + const feedback = { + feedbackType: 'general' as const, + feedbackMessage: 'Test feedback', + canContact: false, + }; + + await RovoDevFeedbackManager.submitFeedback(feedback); + + expect(Logger.warn).toHaveBeenCalledWith(expect.stringContaining('Network error')); + expect(vscode.window.showErrorMessage).toHaveBeenCalledWith( + 'There was an error submitting your feedback. Please try again later.', + ); + }); + + it('should handle non-Axios errors and log warning', async () => { + const error = new Error('Unexpected error'); mockTransport.mockRejectedValue(error); const feedback = { @@ -170,11 +207,13 @@ describe('RovoDevFeedbackManager', () => { await RovoDevFeedbackManager.submitFeedback(feedback); - expect(RovoDevTelemetryProvider.logError).toHaveBeenCalledWith(error, 'Error submitting Rovo Dev feedback'); + expect(Logger.warn).toHaveBeenCalledWith( + 'Feedback submission failed with unexpected error:', + 'Error: Unexpected error', + ); expect(vscode.window.showErrorMessage).toHaveBeenCalledWith( 'There was an error submitting your feedback. Please try again later.', ); - expect(vscode.window.showInformationMessage).not.toHaveBeenCalled(); }); it('should include context information in payload: BBY', async () => { diff --git a/src/rovo-dev/rovoDevFeedbackManager.ts b/src/rovo-dev/rovoDevFeedbackManager.ts index c0c99b576..9095443ed 100644 --- a/src/rovo-dev/rovoDevFeedbackManager.ts +++ b/src/rovo-dev/rovoDevFeedbackManager.ts @@ -1,10 +1,11 @@ +import { isAxiosError } from 'axios'; import { truncate } from 'lodash'; +import { Logger } from 'src/logger'; import { UserInfo } from 'src/rovo-dev/api/extensionApiTypes'; import * as vscode from 'vscode'; import { ExtensionApi, getAxiosInstance } from './api/extensionApi'; import { MIN_SUPPORTED_ROVODEV_VERSION } from './rovoDevProcessManager'; -import { RovoDevTelemetryProvider } from './rovoDevTelemetryProvider'; interface FeedbackObject { feedbackType: 'bug' | 'reportContent' | 'general'; @@ -91,7 +92,13 @@ export class RovoDevFeedbackManager { data: payload, }); } catch (error) { - RovoDevTelemetryProvider.logError(error, 'Error submitting Rovo Dev feedback'); + if (isAxiosError(error)) { + const status = error.response?.status; + const message = error.message; + Logger.warn(`Feedback submission failed: ${status ? `HTTP ${status}` : 'Network error'} - ${message}`); + } else { + Logger.warn('Feedback submission failed with unexpected error:', String(error)); + } vscode.window.showErrorMessage('There was an error submitting your feedback. Please try again later.'); return; }