jackc/pgx · error

cannot scan NULL into %T

Error message

cannot scan NULL into %T

What it means

This error is returned by the JSON scan plan for types decoded via a custom Unmarshal function when a SQL NULL arrives and the destination cannot represent NULL. The code first tries to zero the pointed-to value (setting nil for pointer, slice, map, and interface element kinds); this error only fires when the destination is a pointer to something else (e.g. *struct or *int), where there is no meaningful zero NULL representation, so decoding is refused.

Solutions

  1. Scan into a pointer, slice, map, or interface destination, which the plan can zero on NULL
  2. Wrap the target type in a Go pointer (e.g. **MyStruct) so NULL can be stored as nil
  3. Change the SQL query with COALESCE or a default so NULL never reaches the scanner
  4. Pre-filter NULLs in the query using WHERE col IS NOT NULL
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at pgtype/json.go:211 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/cfca058f32d2483b. Report an issue: GitHub.

Appendix: source

Thrown at pgtype/json.go:211

}

type scanPlanJSONToJSONUnmarshal struct {
	unmarshal func(data []byte, v any) error
}

func (s *scanPlanJSONToJSONUnmarshal) Scan(src []byte, dst any) error {
	if src == nil {
		dstValue := reflect.ValueOf(dst)
		if dstValue.Kind() == reflect.Pointer {
			el := dstValue.Elem()
			switch el.Kind() {
			case reflect.Pointer, reflect.Slice, reflect.Map, reflect.Interface:
				el.Set(reflect.Zero(el.Type()))
				return nil
			}
		}

		return fmt.Errorf("cannot scan NULL into %T", dst)
	}

	v := reflect.ValueOf(dst)
	if v.Kind() != reflect.Pointer || v.IsNil() {
		return fmt.Errorf("cannot scan into non-pointer or nil destinations %T", dst)
	}

	elem := v.Elem()
	elem.Set(reflect.Zero(elem.Type()))

	return s.unmarshal(src, dst)
}

func (c *JSONCodec) DecodeDatabaseSQLValue(m *Map, oid uint32, format int16, src []byte) (driver.Value, error) {
	if src == nil {
		return nil, nil
	}

View on GitHub (pinned to ec1a0befd2)