google-gemini/gemini-cli · error
A2AClient cancelTask Error [${agentName}]: ${error.message}
Error message
A2AClient cancelTask Error [${agentName}]: ${error.message} What it means
cancelTask wraps any Error thrown by the underlying SDK client.cancelTask({ id: taskId }) with an 'A2AClient cancelTask Error [<agentName>]' prefix and preserves the original via { cause }. The inner message is the real signal: it is typically a JSON-RPC error, a network failure, or a task-state rejection from the remote agent. The wrapping makes the failing operation and agent traceable in logs.
Source
Thrown at packages/core/src/agents/a2a-client-manager.ts:286
throw new Error(`${prefix}: Unexpected error: ${String(error)}`);
}
}
/**
* Cancels a task on an agent.
* @param agentName The name of the agent.
* @param taskId The ID of the task to cancel.
* @returns The cancellation response.
*/
async cancelTask(agentName: string, taskId: string): Promise<Task> {
const client = this.clients.get(agentName);
if (!client) throw new Error(`Agent '${agentName}' not found.`);
try {
return await client.cancelTask({ id: taskId });
} catch (error: unknown) {
const prefix = `A2AClient cancelTask Error [${agentName}]`;
if (error instanceof Error) {
throw new Error(`${prefix}: ${error.message}`, { cause: error });
}
throw new Error(`${prefix}: Unexpected error: ${String(error)}`);
}
}
}
View on GitHub (pinned to 5024443c72)
Solutions
- Inspect error.cause for the real upstream message and HTTP/JSON-RPC code before deciding to retry.
- If the task is already terminal, treat the cancel as a no-op success rather than an error.
- Verify the taskId came from a prior sendMessage/getTask response for the same agent and contextId.
- For transient network errors, retry cancelTask with backoff (the SDK auth-retry is separate and only covers 401/403).
Example fix
// before
const task = await manager.cancelTask(name, taskId);
// after
try {
const task = await manager.cancelTask(name, taskId);
} catch (e) {
const msg = e instanceof Error ? e.cause instanceof Error ? e.cause.message : e.message : String(e);
if (/already.*(cancel|terminal|completed|failed)/i.test(msg)) {
// already done - ignore
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Try / catch
try {
return await manager.cancelTask(agentName, taskId);
} catch (e) {
const cause = e instanceof Error ? e.cause : undefined;
const inner = cause instanceof Error ? cause.message : String(e);
// Treat already-terminal as success
if (/cancel|terminal|completed|failed/i.test(inner)) {
return await manager.getTask(agentName, taskId);
}
throw e;
} Prevention
- Always inspect error.cause to see the real upstream failure code.
- Only persist taskIds from responses of the same agent/context to avoid stale ids.
- Log the prefixed message for traceability across agents.
When it happens
Trigger: The task id does not exist on the remote agent; the task is already in a terminal state (completed/failed/canceled) and cannot be canceled; the remote A2A server returned a JSON-RPC error; a transient network error or timeout (up to the 30-minute A2A_TIMEOUT) interrupted the request; the auth token expired and retry was exhausted.
Common situations: Stale taskId persisted from a previous session and reused after the remote purged it; cancelling a task that already finished; remote agent restarted and lost in-memory task state; proxy or TLS misconfiguration causing the SDK fetch to reject.
Related errors
- Failed to clone Git repository from ${installMetadata.source
- [A2AClientManager] sendMessageStream Error [${agentName}]: $
- A2AClient getTask Error [${agentName}]: ${error.message}
- A2AClient cancelTask Error [${agentName}]: Unexpected error:
- No access token received from token endpoint
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/a5133c9757320957.
Report an issue: GitHub.