google-gemini / google-gemini/gemini-cli
bug(a2a-server): fire-and-forget scheduler.schedule() rejection can crash the whole server process
- Dominant language
- TypeScript
- Stars
- 107k
- Forks
- 14.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 45
Description
## What happened?
The A2A server schedules tool batches with a deliberately fire-and-forget promise:
```ts
// Fire and forget so we don't block the executor loop before waitForPendingTools can be called
void this.scheduler.schedule(updatedRequests, abortSignal);
```
But `CoreToolScheduler.schedule()` **legitimately rejects**: `_enqueueRequest()` rejects with `'Tool call cancelled while in queue.'` when the signal aborts while queued, and with `'Operation cancelled'` if already aborted (`packages/core/src/scheduler/scheduler.ts:229-243`). Discarding the promise with `void` turns those rejections into **unhandled rejections**, which under Node's default mode (`--unhandled-rejections=throw`, default since Node 15) terminate the entire a2a-server process — taking down every other running task.
## Affected code
`packages/a2a-server/src/agent/task.ts:817-818`:
```ts
void this.scheduler.schedule(updatedRequests, abortSignal);
```
## How can this be reproduced?
1. Start a task that runs two sequential tool batches.
2. While batch 2 is queued behind batch 1, abort the task (client cancel / socket close triggers `abortController.abort()` in executor.ts).
3. If batch 2 was enqueued before the abort raced the dequeue, `_enqueueRequest` rejects → unhandled rejection → server exits.
Note: PR #27686 codifies `void` as the idiomatic *lint* marker for intentional fire-and-forget, but does not add rejection handling; the hazard here is the un-handled rejection path itself, not the style.
## What did you expect to happen?
Cancellation should be swallowed explicitly (e.g., `.catch(err => { if (!isAbortError(err)) logger.error(err); })`) so aborting one task never kills unrelated tasks.
## Suggested direction
Attach a targeted `.catch()` that treats abort/cancel errors as expected and logs anything else.
---
*Found by source audit on current `main` (commit `5411f113c`); platform-independent. No open issue covering this crash path was found (searched: a2a unhandled rejection).*
Contributor guide
Research direction
Start in packages/a2a-server/src/agent/task.ts:817-818, then inspect the rejection paths in packages/core/src/scheduler/scheduler.ts:229-243 and the abort flow in executor.ts. Verify that expected cancellation does not create an unhandled rejection or terminate the server, while unexpected scheduler errors are logged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100