From 764016bca77ff0e095477e1bb1455af3b671bdd2 Mon Sep 17 00:00:00 2001 From: Emily Hedlund Date: Wed, 14 Jan 2026 12:04:51 -0500 Subject: [PATCH] fix(a2a): Don't throw errors for GeminiEventType Retry and InvalidStream. (#16541) Co-authored-by: Gal Zahavi <38544478+galz10@users.noreply.github.com> --- packages/a2a-server/src/agent/task.test.ts | 38 ++++++++++++++++++++++ packages/a2a-server/src/agent/task.ts | 4 +++ 2 files changed, 42 insertions(+) diff --git a/packages/a2a-server/src/agent/task.test.ts b/packages/a2a-server/src/agent/task.test.ts index 148ce21531..9b5bca8c5c 100644 --- a/packages/a2a-server/src/agent/task.test.ts +++ b/packages/a2a-server/src/agent/task.test.ts @@ -349,6 +349,44 @@ describe('Task', () => { }), ); }); + + it.each([ + { eventType: GeminiEventType.Retry, eventName: 'Retry' }, + { eventType: GeminiEventType.InvalidStream, eventName: 'InvalidStream' }, + ])( + 'should handle $eventName event without triggering error handling', + async ({ eventType }) => { + const mockConfig = createMockConfig(); + const mockEventBus: ExecutionEventBus = { + publish: vi.fn(), + on: vi.fn(), + off: vi.fn(), + once: vi.fn(), + removeAllListeners: vi.fn(), + finished: vi.fn(), + }; + + // @ts-expect-error - Calling private constructor + const task = new Task( + 'task-id', + 'context-id', + mockConfig as Config, + mockEventBus, + ); + + const cancelPendingToolsSpy = vi.spyOn(task, 'cancelPendingTools'); + const setTaskStateSpy = vi.spyOn(task, 'setTaskStateAndPublishUpdate'); + + const event = { + type: eventType, + }; + + await task.acceptAgentMessage(event); + + expect(cancelPendingToolsSpy).not.toHaveBeenCalled(); + expect(setTaskStateSpy).not.toHaveBeenCalled(); + }, + ); }); describe('_schedulerToolCallsUpdate', () => { diff --git a/packages/a2a-server/src/agent/task.ts b/packages/a2a-server/src/agent/task.ts index 187c155808..7bf5e5ad4c 100644 --- a/packages/a2a-server/src/agent/task.ts +++ b/packages/a2a-server/src/agent/task.ts @@ -707,6 +707,10 @@ export class Task { case GeminiEventType.ModelInfo: this.modelInfo = event.value; break; + case GeminiEventType.Retry: + case GeminiEventType.InvalidStream: + // An invalid stream should trigger a retry, which requires no action from the user. + break; case GeminiEventType.Error: default: { // Block scope for lexical declaration