{"id":"6b557b0dcf17a4cc","repo":"jackc/pgx","slug":"range-element-oid-not-registered","errorCode":null,"errorMessage":"range element OID not registered","messagePattern":"range element OID not registered","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"conn.go","lineNumber":1347,"sourceCode":"\t\treturn &pgtype.Type{Name: typeName, OID: oid, Codec: &pgtype.CompositeCodec{Fields: fields}}, nil\n\tcase \"d\": // domain\n\t\tdt, ok := c.TypeMap().TypeForOID(typbasetype)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"domain base type OID not registered\")\n\t\t}\n\n\t\treturn &pgtype.Type{Name: typeName, OID: oid, Codec: dt.Codec}, nil\n\tcase \"e\": // enum\n\t\treturn &pgtype.Type{Name: typeName, OID: oid, Codec: &pgtype.EnumCodec{}}, nil\n\tcase \"r\": // range\n\t\telementOID, err := c.getRangeElementOID(ctx, oid)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tdt, ok := c.TypeMap().TypeForOID(elementOID)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"range element OID not registered\")\n\t\t}\n\n\t\treturn &pgtype.Type{Name: typeName, OID: oid, Codec: &pgtype.RangeCodec{ElementType: dt}}, nil\n\tcase \"m\": // multirange\n\t\telementOID, err := c.getMultiRangeElementOID(ctx, oid)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tdt, ok := c.TypeMap().TypeForOID(elementOID)\n\t\tif !ok {\n\t\t\treturn nil, errors.New(\"multirange element OID not registered\")\n\t\t}\n\n\t\treturn &pgtype.Type{Name: typeName, OID: oid, Codec: &pgtype.MultirangeCodec{ElementType: dt}}, nil\n\tdefault:\n\t\treturn &pgtype.Type{}, errors.New(\"unknown typtype\")\n\t}","sourceCodeStart":1329,"sourceCodeEnd":1365,"githubUrl":"https://github.com/jackc/pgx/blob/ec1a0befd22592cffffdeeb0a50311b506372f4c/conn.go#L1329-L1365","documentation":"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.","triggerScenarios":"Calling Conn.LoadType on a custom range (e.g. CREATE TYPE myrange AS RANGE (subtype=mytype)) before the subtype 'mytype' is loaded and registered.","commonSituations":"Custom range subtypes defined over user types; loading range types before their element types; migrations adding ranges over newly-created base types.","solutions":["LoadType and register the range's element type first, then LoadType the range.","Inspect pg_range.rngsubtype to discover the element OID and ensure it is registered.","Register the element codec manually if it is non-standard.","Order LoadType calls: scalar element → range → (optionally) multirange."],"exampleFix":"// before\nrt, err := conn.LoadType(ctx, \"myrange\") // subtype 'mytype' unknown\n// -> \"range element OID not registered\"\n\n// after\nelem, err := conn.LoadType(ctx, \"mytype\")\nif err != nil { return err }\nconn.TypeMap().RegisterType(elem)\nrt, err := conn.LoadType(ctx, \"myrange\")","handlingStrategy":"validation","validationCode":"// look up pg_range.rngsubtype, register it, then load the range\nvar elemOID uint32\nconn.QueryRow(ctx, \"select rngsubtype from pg_range where rngtypid=$1::regtype::oid\", rangeName).Scan(&elemOID)\nif _, ok := conn.TypeMap().TypeForOID(elemOID); !ok {\n    // LoadType element, register, then LoadType range\n}","typeGuard":"func rangeElementRegistered(m *pgtype.Map, elemOID uint32) bool { _, ok := m.TypeForOID(elemOID); return ok }","tryCatchPattern":"if t, err := conn.LoadType(ctx, rangeName); err != nil {\n    if strings.Contains(err.Error(), \"range element OID not registered\") {\n        // load+register element, retry\n    }\n    return nil, err\n}","preventionTips":["LoadType element types before range types.","Order registration: element → range → multirange.","Register custom element codecs explicitly."],"tags":["types","loadtype","registration","range"],"analyzedSha":"ec1a0befd22592cffffdeeb0a50311b506372f4c","analyzedAt":"2026-08-04T22:52:11.263Z","schemaVersion":2}