{"record":{"id":"8d5f7f6511dbbde1","repo":"google-gemini/gemini-cli","slug":"operation-aborted","errorCode":null,"errorMessage":"Operation aborted","messagePattern":"Operation aborted","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/core/src/agents/remote-invocation.ts","lineNumber":188,"sourceCode":"      }\n\n      const message = this.params.query;\n\n      const stream = this.clientManager.sendMessageStream(\n        this.definition.name,\n        message,\n        {\n          contextId: this.contextId,\n          taskId: this.taskId,\n          signal: _signal,\n        },\n      );\n\n      let finalResponse: SendMessageResult | undefined;\n\n      for await (const chunk of stream) {\n        if (_signal.aborted) {\n          throw new Error('Operation aborted');\n        }\n        finalResponse = chunk;\n        reassembler.update(chunk);\n\n        if (updateOutput) {\n          updateOutput({\n            isSubagentProgress: true,\n            agentName,\n            state: SubagentState.RUNNING,\n            recentActivity: reassembler.toActivityItems(),\n            result: reassembler.toString(),\n          });\n        }\n\n        const {\n          contextId: newContextId,\n          taskId: newTaskId,\n          clearTaskId,","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/core/src/agents/remote-invocation.ts#L170-L206","documentation":"Thrown inside the streaming loop of RemoteAgentInvocation.execute() when _signal.aborted becomes true between chunks. This is the cooperative-cancellation path: an external AbortSignal (user cancel, parent abort, timeout) fired while consuming the remote agent's response stream.","triggerScenarios":"for await (const chunk of stream) checks _signal.aborted each iteration; any abort (user pressed stop, the parent task was cancelled, a timeout aborted the signal) flips the flag and this throws on the next iteration.","commonSituations":"User cancels the running agent; a parent subagent is aborted; an AbortController timeout fires mid-stream; upstream scheduler cancels the task.","solutions":["Treat as expected cancellation — surface a 'cancelled by user' message rather than an error where appropriate.","If unintended, investigate which AbortController is aborting the signal (timeout, parent shutdown).","Ensure cleanup in the finally block persists session state (it does) so the conversation can resume.","Raise the relevant timeout if the abort came from a too-short deadline."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pass a signal with a generous deadline and avoid aborting mid-stream unless intended.\nconst ctrl = new AbortController();\nconst timer = setTimeout(() => ctrl.abort(), 5 * 60_000);\n// ... pass ctrl.signal, clear timer when done.","typeGuard":"function isAbortError(e) {\n  return e instanceof Error && (e.name === 'AbortError' || /Operation aborted/.test(e.message));\n}","tryCatchPattern":"try {\n  await invocation.execute({ abortSignal: signal });\n} catch (e) {\n  if (e instanceof Error && e.message === 'Operation aborted') {\n    // user/parent cancellation — report cleanly, do not rethrow as a hard error\n    return { cancelled: true };\n  }\n  throw e;\n}","preventionTips":["Distinguish cancellation from real errors in the UI layer.","Do not set extremely short deadlines on remote-agent streams.","Ensure session state is persisted so a cancelled run can resume."],"tags":["a2a","agents","abort","cancellation"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}