jackc/pgx · error

range element OID not registered

Error message

range element OID not registered

What it means

Returned by Conn.LoadType for a typtype='r' (range) type when the range's element OID (looked up via pg_range) is not in the connection's TypeMap (conn.go:1345-1347). Range codecs wrap an element codec; if the element is unknown, the range cannot be decoded/encoded.

Source

Thrown at conn.go:1347

		return &pgtype.Type{Name: typeName, OID: oid, Codec: &pgtype.CompositeCodec{Fields: fields}}, nil
	case "d": // domain
		dt, ok := c.TypeMap().TypeForOID(typbasetype)
		if !ok {
			return nil, errors.New("domain base type OID not registered")
		}

		return &pgtype.Type{Name: typeName, OID: oid, Codec: dt.Codec}, nil
	case "e": // enum
		return &pgtype.Type{Name: typeName, OID: oid, Codec: &pgtype.EnumCodec{}}, nil
	case "r": // range
		elementOID, err := c.getRangeElementOID(ctx, oid)
		if err != nil {
			return nil, err
		}

		dt, ok := c.TypeMap().TypeForOID(elementOID)
		if !ok {
			return nil, errors.New("range element OID not registered")
		}

		return &pgtype.Type{Name: typeName, OID: oid, Codec: &pgtype.RangeCodec{ElementType: dt}}, nil
	case "m": // multirange
		elementOID, err := c.getMultiRangeElementOID(ctx, oid)
		if err != nil {
			return nil, err
		}

		dt, ok := c.TypeMap().TypeForOID(elementOID)
		if !ok {
			return nil, errors.New("multirange element OID not registered")
		}

		return &pgtype.Type{Name: typeName, OID: oid, Codec: &pgtype.MultirangeCodec{ElementType: dt}}, nil
	default:
		return &pgtype.Type{}, errors.New("unknown typtype")
	}

View on GitHub (pinned to ec1a0befd2)

Solutions

  1. LoadType and register the range's element type first, then LoadType the range.
  2. Inspect pg_range.rngsubtype to discover the element OID and ensure it is registered.
  3. Register the element codec manually if it is non-standard.
  4. Order LoadType calls: scalar element → range → (optionally) multirange.

Example fix

// before
rt, err := conn.LoadType(ctx, "myrange") // subtype 'mytype' unknown
// -> "range element OID not registered"

// after
elem, err := conn.LoadType(ctx, "mytype")
if err != nil { return err }
conn.TypeMap().RegisterType(elem)
rt, err := conn.LoadType(ctx, "myrange")
Defensive patterns

Strategy: validation

Validate before calling

// look up pg_range.rngsubtype, register it, then load the range
var elemOID uint32
conn.QueryRow(ctx, "select rngsubtype from pg_range where rngtypid=$1::regtype::oid", rangeName).Scan(&elemOID)
if _, ok := conn.TypeMap().TypeForOID(elemOID); !ok {
    // LoadType element, register, then LoadType range
}

Type guard

func rangeElementRegistered(m *pgtype.Map, elemOID uint32) bool { _, ok := m.TypeForOID(elemOID); return ok }

Try / catch

if t, err := conn.LoadType(ctx, rangeName); err != nil {
    if strings.Contains(err.Error(), "range element OID not registered") {
        // load+register element, retry
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling Conn.LoadType on a custom range (e.g. CREATE TYPE myrange AS RANGE (subtype=mytype)) before the subtype 'mytype' is loaded and registered.

Common situations: Custom range subtypes defined over user types; loading range types before their element types; migrations adding ranges over newly-created base types.

Related errors


AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04). Data as JSON: /data/errors/6b557b0dcf17a4cc.json. Report an issue: GitHub.