Trace streaming cancellation as a request outcome and a propagation path. Record when cancellation was observed, which operations stopped, what output had already been delivered, and whether a consequential action had already completed.
A closed tab is not a completed task
A client may disconnect after the first chunk while the application continues generation or starts a tool. A single “stream closed” event hides whether work stopped, finished, or failed. Keep user cancellation distinct from provider failure and successful completion.
Exercise cancellation at meaningful points
- Cancel before generation starts and confirm no unnecessary downstream work begins.
- Cancel after one chunk and record partial delivery without treating it as a complete answer.
- Cancel while a tool is running; distinguish cancellation requested from cancellation acknowledged.
- Check that a final-state event is emitted once and that later callbacks do not overwrite it as success.
What AbortSignal does and does not establish
An abort signal communicates cancellation to code that observes it. It does not automatically undo an external side effect or stop a library that ignores the signal. Check the exact client’s cancellation support, timeout behavior, and billing semantics separately.
Read the local example
The fixture uses a local abort signal, emits one chunk, and refuses to produce the next synthetic chunk after abort. Its terminal outcome is canceled with one delivered chunk. It intentionally makes no network call and therefore does not establish cancellation support in a model provider or this application’s streaming endpoint.
Run the worked example
Save the synthetic Node.js example and run node trace-streaming-request-cancellations.mjs with Node.js 22 or newer. The assertions check the illustrated records and calculations; they do not test a deployed provider, SDK, or access control. No credentials or network connection are needed.
// Synthetic teaching fixture. No credentials, network calls, or production verification.
import assert from 'node:assert/strict';
const controller = new AbortController();
const delivered = [];
const emit = text => { controller.signal.throwIfAborted(); delivered.push(text); };
emit('partial answer');
controller.abort();
assert.throws(() => emit('must not be delivered'));
const terminal = { outcome: 'canceled', deliveredChunks: delivered.length };
assert.equal(terminal.deliveredChunks, 1);
assert.equal(terminal.outcome, 'canceled');
console.log(JSON.stringify(terminal));
References and further reading
Maintained by DriftRail. AI assisted the October 2026 content and template revision. Examples are illustrative; they are not measured product benchmarks. Suggest a correction.