jackc/pgx · error

rows is closed

Error message

rows is closed

What it means

baseRows.Values guard: the rows were already closed (explicitly via Close, or implicitly by finishing/aborting the result set) before Values() was called. The stale Rows handle is the faulty input; values can only be read while the rows are open.

Solutions

  1. Call Values() before Rows.Close and before iterating past the last row
  2. Loop with rows.Next() and read values inside the loop body
  3. With CollectRows/ForEachRow, avoid touching the Rows object afterwards
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at rows.go:294 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04). Data as JSON: /api/errors/507bd8324b0b48e4. Report an issue: GitHub.

Appendix: source

Thrown at rows.go:294

		if rows.scanTypes[i] != reflect.TypeOf(dst) {
			rows.scanPlans[i] = m.PlanScan(fieldDescriptions[i].DataTypeOID, fieldDescriptions[i].Format, dest[i])
			rows.scanTypes[i] = reflect.TypeOf(dest[i])
		}

		err := rows.scanPlans[i].Scan(values[i], dst)
		if err != nil {
			err = ScanArgError{ColumnIndex: i, FieldName: fieldDescriptions[i].Name, Err: err}
			rows.fatal(err)
			return err
		}
	}

	return nil
}

func (rows *baseRows) Values() ([]any, error) {
	if rows.closed {
		return nil, errors.New("rows is closed")
	}

	values := make([]any, 0, len(rows.FieldDescriptions()))

	for i := range rows.FieldDescriptions() {
		buf := rows.values[i]
		fd := &rows.FieldDescriptions()[i]

		if buf == nil {
			values = append(values, nil)
			continue
		}

		if dt, ok := rows.typeMap.TypeForOID(fd.DataTypeOID); ok {
			value, err := dt.Codec.DecodeValue(rows.typeMap, fd.DataTypeOID, fd.Format, buf)
			if err != nil {
				rows.fatal(err)
			}

View on GitHub (pinned to ec1a0befd2)