jackc/pgx · error
no reference to batch
Error message
no reference to batch
What it means
Returned by (*pipelineBatchResults).nextQueryAndArgs when br.b is nil — the pipeline BatchResults object has no pointer back to the originating Batch. pgx constructs pipelineBatchResults with b set inside SendBatch, so a nil batch indicates an internal invariant violation or a result object that was not produced through the normal SendBatch path. The reader cannot correlate the next server result with any queued query.
Source
Thrown at batch.go:443
}
br.closed = true
err := br.pipeline.Close()
if br.err == nil {
br.err = err
}
return br.err
}
func (br *pipelineBatchResults) earlyError() error {
return br.err
}
func (br *pipelineBatchResults) nextQueryAndArgs() (query string, args []any, err error) {
if br.b == nil {
return "", nil, errors.New("no reference to batch")
}
if br.qqIdx >= len(br.b.QueuedQueries) {
return "", nil, errors.New("no more results in batch")
}
bi := br.b.QueuedQueries[br.qqIdx]
br.qqIdx++
return bi.SQL, bi.Arguments, nil
}
type emptyBatchResults struct {
conn *Conn
closed bool
}
// Exec reads the results from the next query in the batch as if the query has been sent with Exec.
func (br *emptyBatchResults) Exec() (pgconn.CommandTag, error) {View on GitHub (pinned to ec1a0befd2)
Solutions
- Only obtain BatchResults from Conn.SendBatch (or the pool/tx equivalents); never construct pipelineBatchResults yourself.
- Report this as a pgx bug if reached through the public API — the batch pointer should always be populated.
- If writing a custom BatchResults implementation for testing, return emptyBatchResults or your own type rather than reusing pipelineBatchResults.
- Update to the latest pgx patch release in case the invariant was restored.
Example fix
// before (test double)
br := &pipelineBatchResults{ctx: ctx, conn: c, pipeline: p} // missing b
_, err := br.Exec()
// after
br := &pipelineBatchResults{ctx: ctx, conn: c, pipeline: p, b: batch} Defensive patterns
Strategy: validation
Validate before calling
// Only ever obtain BatchResults from SendBatch:
if batch == nil || len(batch.QueuedQueries) == 0 {
// send nothing / use emptyBatchResults semantics
return nil
}
br := conn.SendBatch(ctx, batch) Try / catch
if _, err := br.Exec(); err != nil {
if strings.Contains(err.Error(), "no reference to batch") {
return fmt.Errorf("internal: BatchResults has no batch; report upstream")
}
return err
} Prevention
- Never construct pipelineBatchResults by hand.
- Obtain BatchResults only through Conn/Pool/Tx SendBatch.
- Treat 'no reference to batch' as an internal-invariant bug and report it.
When it happens
Trigger: Calling Exec()/Query()/QueryRow() on a *pipelineBatchResults whose Batch pointer is nil. In normal API use SendBatch always sets it, so this surfaces from internal construction bugs, reflection/test doubles that build pipelineBatchResults without b, or a future code path that sends a pipeline query without a Batch.
Common situations: Test scaffolding or wrappers that synthesize BatchResults manually; an internal pgx bug after a refactor; calling methods on a pipelineBatchResults struct created directly rather than via SendBatch.
Related errors
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/3e7ab340ecea96ad.json.
Report an issue: GitHub.