jackc/pgx · error
unknown typtype
Error message
unknown typtype
What it means
Returned by Conn.LoadType when pg_type.typtype of the requested type is not one of b/c/d/e/r/m (base/composite/domain/enum/range/multirange). The switch falls through to default at conn.go:1364. This usually means the type is a pseudo-type (typtype='p', e.g. void, anyelement, trigger, record), a table row type, or a typtype introduced by a newer PostgreSQL version pgx does not yet handle.
Source
Thrown at conn.go:1364
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")
}
}
func (c *Conn) getArrayElementOID(ctx context.Context, oid uint32) (uint32, error) {
var typelem uint32
err := c.QueryRow(ctx, "select typelem from pg_type where oid=$1", oid).Scan(&typelem)
if err != nil {
return 0, err
}
return typelem, nil
}
func (c *Conn) getRangeElementOID(ctx context.Context, oid uint32) (uint32, error) {
var typelem uint32
err := c.QueryRow(ctx, "select rngsubtype from pg_range where rngtypid=$1", oid).Scan(&typelem)View on GitHub (pinned to ec1a0befd2)
Solutions
- Do not call LoadType on pseudo-types or table row types; they are not derivable types pgx models.
- For a table-like payload, define a CREATE TYPE … AS (…) composite and LoadType that name.
- Upgrade pgx — newer versions may handle additional typtypes.
- Check SELECT typtype FROM pg_type WHERE typname=… to confirm the kind before calling LoadType.
Example fix
// before
t, err := conn.LoadType(ctx, "trigger") // typtype='p' -> unknown typtype
// after
var tt string
conn.QueryRow(ctx, "select typtype::text from pg_type where typname=$1", name).Scan(&tt)
if tt != "b" && tt != "c" && tt != "d" && tt != "e" && tt != "r" && tt != "m" {
return nil, fmt.Errorf("type %s is %q, not LoadType-able", name, tt)
} Defensive patterns
Strategy: validation
Validate before calling
var tt string
if err := conn.QueryRow(ctx, "select typtype::text from pg_type where typname=$1", name).Scan(&tt); err != nil { return err }
switch tt {
case "b","c","d","e","r","m":
// LoadType-able
default:
return fmt.Errorf("type %s has typtype %q; pgx cannot LoadType it", name, tt)
}
return nil Type guard
func loadTypeable(tt string) bool {
switch tt {
case "b","c","d","e","r","m": return true
}
return false
} Try / catch
if t, err := conn.LoadType(ctx, name); err != nil {
if strings.Contains(err.Error(), "unknown typtype") {
// not a LoadType-able type; skip
return nil, nil
}
return nil, err
} Prevention
- Check typtype via pg_type before calling LoadType.
- Do not LoadType pseudo-types or table row types.
- Upgrade pgx to gain support for newer typtypes.
When it happens
Trigger: Calling Conn.LoadType on a pseudo-type (e.g. 'record', 'anyelement', 'trigger', 'void'), a table's implicit row type, or a brand-new kind of type added by a future/extension PostgreSQL version.
Common situations: Trying to LoadType a table name (row types are 'c' composites only for CREATE TYPE AS composites; tables expose row types that LoadType does not model); pointing LoadType at 'anyelement'/generic types; an extension introducing a novel typtype.
Related errors
- array element OID not registered
- domain base type OID not registered
- range element OID not registered
- multirange element OID not registered
- AuthTypeSCMCreds is unimplemented
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/4a565ea5faa3275b.json.
Report an issue: GitHub.