diff --git a/packages/cli/src/ui/components/EditorSettingsDialog.test.tsx b/packages/cli/src/ui/components/EditorSettingsDialog.test.tsx
index 18b47def7b..7646ac4817 100644
--- a/packages/cli/src/ui/components/EditorSettingsDialog.test.tsx
+++ b/packages/cli/src/ui/components/EditorSettingsDialog.test.tsx
@@ -175,4 +175,45 @@ describe('EditorSettingsDialog', () => {
}
expect(frame).toContain('(Also modified');
});
+
+ it('emits error feedback only once when preferredEditor is invalid', async () => {
+ const mockEmitFeedback = vi.fn();
+ vi.spyOn(
+ await import('@google/gemini-cli-core').then((m) => m.coreEvents),
+ 'emitFeedback',
+ ).mockImplementation(mockEmitFeedback);
+
+ const invalidSettings = {
+ forScope: (_scope: string) => ({
+ settings: {
+ general: {
+ preferredEditor: 'invalideditor',
+ },
+ },
+ }),
+ merged: {
+ general: {
+ preferredEditor: 'invalideditor',
+ },
+ },
+ } as unknown as LoadedSettings;
+
+ const { unmount } = await renderWithProvider(
+ ,
+ );
+
+ await waitFor(() => {
+ expect(mockEmitFeedback).toHaveBeenCalledWith(
+ 'error',
+ 'Editor is not supported: invalideditor',
+ );
+ });
+
+ expect(mockEmitFeedback).toHaveBeenCalledTimes(1);
+ unmount();
+ });
});
diff --git a/packages/cli/src/ui/components/EditorSettingsDialog.tsx b/packages/cli/src/ui/components/EditorSettingsDialog.tsx
index 7fa0d2a2cf..41d27c4bfb 100644
--- a/packages/cli/src/ui/components/EditorSettingsDialog.tsx
+++ b/packages/cli/src/ui/components/EditorSettingsDialog.tsx
@@ -5,7 +5,7 @@
*/
import type React from 'react';
-import { useState } from 'react';
+import { useState, useEffect, useRef } from 'react';
import { Box, Text } from 'ink';
import { theme } from '../semantic-colors.js';
import {
@@ -71,14 +71,26 @@ export function EditorSettingsDialog({
(item: EditorDisplay) => item.type === currentPreference,
)
: 0;
- if (editorIndex === -1) {
- coreEvents.emitFeedback(
- 'error',
- `Editor is not supported: ${currentPreference}`,
- );
+ const isUnsupportedEditor = editorIndex === -1;
+ if (isUnsupportedEditor) {
editorIndex = 0;
}
+ const reportedInvalidEditors = useRef(new Set());
+ useEffect(() => {
+ if (
+ isUnsupportedEditor &&
+ currentPreference &&
+ !reportedInvalidEditors.current.has(currentPreference)
+ ) {
+ coreEvents.emitFeedback(
+ 'error',
+ `Editor is not supported: ${currentPreference}`,
+ );
+ reportedInvalidEditors.current.add(currentPreference);
+ }
+ }, [isUnsupportedEditor, currentPreference]);
+
const scopeItems: Array<{
label: string;
value: LoadableSettingScope;