jackc/pgx · error

range lower bound cannot be NULL

Error message

range lower bound cannot be NULL

What it means

In the binary range format, a bounded lower bound must be encoded as a non-NULL value (length-prefixed bytes). The reader returned the NULL marker even though the flags byte said the lower bound was bounded — an internally contradictory payload.

Solutions

  1. Treat the binary range as corrupt and reject it
  2. Verify the producer encodes bounded bounds as non-NULL values
  3. Use unbounded flags (or SQL NULL) when a bound is absent
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at pgtype/range.go:242 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/84ea583292c7ee04. Report an issue: GitHub.

Appendix: source

Thrown at pgtype/range.go:242

	case rangeType&lowerUnboundedMask > 0:
		ubr.LowerType = Unbounded
	default:
		ubr.LowerType = Exclusive
	}

	switch {
	case rangeType&upperInclusiveMask > 0:
		ubr.UpperType = Inclusive
	case rangeType&upperUnboundedMask > 0:
		ubr.UpperType = Unbounded
	default:
		ubr.UpperType = Exclusive
	}

	if ubr.LowerType != Unbounded {
		val, null := r.Value()
		if null {
			return nil, fmt.Errorf("range lower bound cannot be NULL")
		}
		ubr.Lower = val
	}

	if ubr.UpperType != Unbounded {
		val, null := r.Value()
		if null {
			return nil, fmt.Errorf("range upper bound cannot be NULL")
		}
		ubr.Upper = val
	}

	if err := r.Finish(); err != nil {
		return nil, fmt.Errorf("range: %w", err)
	}

	return ubr, nil
}

View on GitHub (pinned to ec1a0befd2)