When the context is canceled mid-batch, processor.Channel.Process returns immediately with the remaining unsent items untouched (processor/channel.go:30-34):
select {
case <-ctx.Done():
return items, ctx.Err()
case p.Output <- item.Data:
}
The stage error becomes a single ProcessorError, but every item that never reached Output comes back with Error == nil — per-item accounting says "delivered" for data that was never sent.
Repro sketch: unbuffered Output with a slow consumer, cancel the context after the first send; items 2..N are reported as processed successfully.
Suggested fix: mark undelivered items with ctx.Err() before returning (same pattern as processor.Nil's MarkCancelled), so downstream error accounting reflects reality.
Found in the 2026-07-10 full-repo review (verified by repro).
When the context is canceled mid-batch,
processor.Channel.Processreturns immediately with the remaining unsent items untouched (processor/channel.go:30-34):The stage error becomes a single
ProcessorError, but every item that never reachedOutputcomes back withError == nil— per-item accounting says "delivered" for data that was never sent.Repro sketch: unbuffered
Outputwith a slow consumer, cancel the context after the first send; items 2..N are reported as processed successfully.Suggested fix: mark undelivered items with
ctx.Err()before returning (same pattern asprocessor.Nil'sMarkCancelled), so downstream error accounting reflects reality.Found in the 2026-07-10 full-repo review (verified by repro).