pgx icon indicating copy to clipboard operation
pgx copied to clipboard

unexpected pipeline result: *pgconn.PipelineSync

Open janisz opened this issue 2 years ago • 6 comments

Describe the bug When usign a batch to insert an object I've got following error: unexpected pipeline result: *pgconn.PipelineSync

To Reproduce Steps to reproduce the behavior:

I've failed to reproduce

Expected behavior Error message will tell what's the problem is.

Actual behavior Error message that looks like internal pgx issue.

Version

  • Go: go1.20.4 linux/amd64
  • pgx: v5.5.0

Additional context Add any other context about the problem here.

janisz avatar Nov 17 '23 15:11 janisz

In case somebody encounters this issue, on pgx v.5.5.5, the error was triggered by calling batchReq.Exec() after sending a batch update (or insert).

Example:

var b pgx.Batch
sql := `UPDATE table SET field = $1 WHERE other=$2`
for x,y := range stuff {
  b.Queue(sql, x, y)
}

batchReq := c.conn.SendBatch(ctx, &b)
defer func() {
  err = batchReqClose(err, batchReq)
}()

_, err := batchReq.Exec()

return err

Removing _, err := batchReq.Exec() fixed the issue for me.

However I'll note that this issue doesn't always happen, not sure what is triggering condition but I have a service with that code that never triggers the *pgconn.PipelineSync error, while another service will suddenly start getting it. If anyone has an idea as to what can cause the behaviour that'd be interesting to know.

michel-kiln avatar May 30 '24 13:05 michel-kiln

I've been able to get this to reproduce reliably when the update batch is of 0 queries. Yes, that sounds silly on the surface, but sometimes there's nothing where you'd normally expect something, when you're getting your data programmatically. Our solution for this was to check that the Batch's .Len() != 0 before calling Exec, but depending on where you're getting your data, you may be able to determine that there's nothing sooner.

LiruMouse avatar Jul 01 '24 16:07 LiruMouse

@LiruMouse

Do you have an example of this?

I just created a simple test that sent a batch with 0 queries and it didn't crash.

batch := &pgx.Batch{}
br := conn.SendBatch(ctx, batch)
err := br.Close()
require.NoError(t, err)

jackc avatar Jul 02 '24 12:07 jackc

Interesting, @jackc, I'll try to paraphrase and summarize our code to demonstrate (please endure any semantic errors, though) We're taking rows from another database, which has a simple iterator interface. So please assume that query_from_row builds proper queries based on the data in row_iter, and calls batch.Queue on that query, with the necessary data from the row.

batch := &pgx.Batch{}
for row_iter.Next() {
    queue_query_from_row(row_iter, &batch) // batch.Queue
}
br := conn.SendBatch(ctx, batch)
defer br.Close()
tag, err := br.Exec()

Is it that call to Exec?

LiruMouse avatar Jul 02 '24 16:07 LiruMouse

@LiruMouse

So, trying to read more results than queries were included in the batch? That's probably a bug in the application. I've added some additional checks to return a better error message in dced53f79657fa287825038ea606e696a72d5dd2. But I don't think this is a pgx bug.

jackc avatar Jul 04 '24 03:07 jackc

@LiruMouse

So, trying to read more results than queries were included in the batch? That's probably a bug in the application. I've added some additional checks to return a better error message in dced53f. But I don't think this is a pgx bug.

I completely agree, this is a bug in the application, where the end developer expects there to be more data available to create queries, but in certain cases that is not so.

Thanks for improving the error, that should help users understand this particular problem in the future.

LiruMouse avatar Jul 04 '24 05:07 LiruMouse