Current outcome
Prevent accidentally consuming and discarding an input stream when a caller forgets the processor chain, while keeping intentional discard explicit.
Replanned on 2026-09-06 against GoBatch master 63ef757 and ShitQuant's recorder, enrichment, paper/replay, and flow workloads. This is an implementation target, not a claim that the behavior already exists.
Required behavior
Verification and completion
Assert no source reads on failed start, effective-chain cases, the chosen typed-nil behavior, successful corrected retry where promised, and deliberate discard.
Follow the repository's formatting, race-test, vet/lint, package documentation, example and changelog requirements for the changed surface. Report the actual supported behavior and migration; do not treat a passing coverage percentage as proof of these outcomes.
Scope and relationships
Independent of request batching and flow. Reconcile edits with open core PRs without requiring unrelated documentation PRs to merge first.
Design history
The earlier report/prototype remains below for provenance; the requirements above supersede conflicting prescriptions. Existing discussion is preserved.
Original issue: Require at least one Processor in Batch.Go (use processor.Nil for explicit drain)
Summary
Batch.Go(ctx, s, procs ...Processor[T]) currently accepts zero processors. With no processors the pipeline reads the source, discards every item, surfaces source errors, and fires Done(). That is a silent-data-discard footgun: forgetting to pass a processor produces a clean, error-free run that did nothing with the data — the same class of issue as a nil source (now ErrNilSource, see #64).
Proposal
Require at least one Processor. Callers who genuinely want to drain/discard a source pass an explicit no-op (&processor.Nil[T]{}, which already exists), so the intent is explicit at the call site instead of implicit.
Why
Tradeoffs to weigh
- Breaks variadic ergonomics for the degenerate zero-stage case.
- Breaks graceful handling of dynamically built processor lists that can legitimately be empty — callers would need to guard or substitute
processor.Nil.
- Breaks existing tests that assert no-processors is allowed:
TestBatch_NoProcessors (batch/batch_test.go) and the empty-processor-slice case in batch/error_handling_test.go.
- Breaking change (v0) → migration note + CHANGELOG entry.
Alternatives considered
- Document current behavior — keep allowing zero processors, add a godoc line that it drains and discards items (source errors still surface). Lower friction, keeps the footgun.
- Leave entirely as-is.
References
Current outcome
Prevent accidentally consuming and discarding an input stream when a caller forgets the processor chain, while keeping intentional discard explicit.
Replanned on 2026-09-06 against GoBatch master
63ef757and ShitQuant's recorder, enrichment, paper/replay, and flow workloads. This is an implementation target, not a claim that the behavior already exists.Required behavior
Verification and completion
Assert no source reads on failed start, effective-chain cases, the chosen typed-nil behavior, successful corrected retry where promised, and deliberate discard.
Follow the repository's formatting, race-test, vet/lint, package documentation, example and changelog requirements for the changed surface. Report the actual supported behavior and migration; do not treat a passing coverage percentage as proof of these outcomes.
Scope and relationships
Independent of request batching and flow. Reconcile edits with open core PRs without requiring unrelated documentation PRs to merge first.
Design history
The earlier report/prototype remains below for provenance; the requirements above supersede conflicting prescriptions. Existing discussion is preserved.
Original issue: Require at least one Processor in Batch.Go (use processor.Nil for explicit drain)
Summary
Batch.Go(ctx, s, procs ...Processor[T])currently accepts zero processors. With no processors the pipeline reads the source, discards every item, surfaces source errors, and firesDone(). That is a silent-data-discard footgun: forgetting to pass a processor produces a clean, error-free run that did nothing with the data — the same class of issue as a nil source (nowErrNilSource, see #64).Proposal
Require at least one
Processor. Callers who genuinely want to drain/discard a source pass an explicit no-op (&processor.Nil[T]{}, which already exists), so the intent is explicit at the call site instead of implicit.Gowith zero processors returns a start error (e.g.ErrNoProcessors), consistent with theErrNilSource/ErrBatchUsedcontract added in feat(batch)!: single-use Batch + Go returns (<-chan error, error); inline item IDs #64.b.Go(ctx, src, &processor.Nil[T]{}).Why
ErrNilSource, reused Batch →ErrBatchUsed).Tradeoffs to weigh
processor.Nil.TestBatch_NoProcessors(batch/batch_test.go) and the empty-processor-slice case inbatch/error_handling_test.go.Alternatives considered
References
ErrNilSource,ErrBatchUsed) and theExecuteBatchesnil-source fix that motivated this question.Batch.doProcessors(batch/batch.go); the no-op no-processors path is exercised byTestBatch_NoProcessors.