Skip to content

Commit 98f96d5

Browse files
gijswalravenGijs Walravenclauderokonec
authored
fix: CancelTaskAsync re-fetches task after UpdateStatusAsync (alternative approach) (#283)
* fix: re-fetch task after UpdateStatusAsync in CancelTaskAsync CancelTaskAsync discarded the return value of ITaskStore.UpdateStatusAsync, so the returned AgentTask reflected the pre-cancellation status. Beyond just Status, a custom store may update additional fields during status transitions (e.g. UpdatedAt, ETag). Re-fetching the full task after the update ensures the returned AgentTask is fully authoritative for all store implementations. The bug was masked by InMemoryTaskStore because GetTaskAsync returns a reference to the cached object that UpdateStatusAsync mutates in place. Fixes #277 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: throw instead of silently falling back to stale task on null re-fetch If GetTaskAsync returns null after a successful UpdateStatusAsync, ?? task would return the original object with pre-cancellation status, reintroducing the bug. Throw instead to surface the inconsistency loudly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Gijs Walraven <gijs.walraven@delaware.pro> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Roman Konecny <rokonecn@microsoft.com>
1 parent e9d269e commit 98f96d5

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

src/A2A/Server/TaskManager.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,10 @@ public async Task<AgentTask> CreateTaskAsync(string? contextId = null, string? t
109109
throw new A2AException("Task is in a terminal state and cannot be cancelled.", A2AErrorCode.TaskNotCancelable);
110110
}
111111

112-
task.Status = await _taskStore.UpdateStatusAsync(task.Id, TaskState.Canceled, cancellationToken: cancellationToken).ConfigureAwait(false);
112+
await _taskStore.UpdateStatusAsync(task.Id, TaskState.Canceled, cancellationToken: cancellationToken).ConfigureAwait(false);
113+
task = await _taskStore.GetTaskAsync(task.Id, cancellationToken).ConfigureAwait(false)
114+
?? throw new A2AException("Task not found after cancellation.", A2AErrorCode.TaskNotFound);
115+
113116
await OnTaskCancelled(task, cancellationToken).ConfigureAwait(false);
114117
return task;
115118
}

0 commit comments

Comments
 (0)