Summary
Querying any column of PostgreSQL's internal "char" type (OID 18 — the single-byte character type used extensively in system catalogs) raises a RustToPyValueMappingError. The error message instructs users to use custom_decoders, but passing a decoder for this type to QueryResult.result() has no effect and the exception is still raised.
Environment
- psqlpy: 0.11.12
- Python: 3.14.3
- PostgreSQL: 14.20
Reproduction
import asyncio
import psqlpy
pool = psqlpy.ConnectionPool(
host="127.0.0.1", port=5432, username="postgres", password="...", db_name="postgres",
max_db_pool_size=2,
)
async def main():
async with pool.acquire() as conn:
# "char" columns appear throughout system catalogs, e.g. pg_type:
# typtype, typcategory, typdelim, typalign, typstorage (all OID 18)
result = await conn.execute(
"SELECT typname, typtype FROM pg_type LIMIT 5"
)
# Attempt 1: call result() without custom_decoders
# → RustToPyValueMappingError: Cannot convert char into Python type
# Attempt 2: pass custom_decoders as instructed by the error message
rows = result.result(
custom_decoders={"char": lambda b: b.decode("utf-8")}
)
# → still raises RustToPyValueMappingError (decoder is never called)
asyncio.run(main())
pool.close()
Actual behaviour
psqlpy.exceptions.RustToPyValueMappingError: Can't convert value from driver to python type: Cannot convert char into Python type, please look at the custom_decoders functionality.
The exception is raised both with and without a custom_decoders entry. All key formats tried — "char", "18", 18, "bpchar", "character" — produce the same error, meaning the custom decoder dispatch never reaches user-supplied code for OID 18.
Expected behaviour
Either:
"char" (OID 18) is decoded natively as a single-character Python str (this is what asyncpg, psycopg2, and psycopg3 all do), or
custom_decoders actually dispatches to user code for this OID so the user can supply their own decoder.
Impact
Any query that touches PostgreSQL system catalogs (pg_type, pg_class, pg_attribute, pg_proc, …) will fail. The "char" type is extremely common in catalog tables — pg_type alone has five "char" columns (typtype, typcategory, typdelim, typalign, typstorage).
Notes
"char" (OID 18) is distinct from character(n) / varchar (OID 1042 / 1043). It is a fixed-width single-byte internal type and should map directly to a one-character Python str.
Summary
Querying any column of PostgreSQL's internal
"char"type (OID 18 — the single-byte character type used extensively in system catalogs) raises aRustToPyValueMappingError. The error message instructs users to usecustom_decoders, but passing a decoder for this type toQueryResult.result()has no effect and the exception is still raised.Environment
Reproduction
Actual behaviour
The exception is raised both with and without a
custom_decodersentry. All key formats tried —"char","18",18,"bpchar","character"— produce the same error, meaning the custom decoder dispatch never reaches user-supplied code for OID 18.Expected behaviour
Either:
"char"(OID 18) is decoded natively as a single-character Pythonstr(this is what asyncpg, psycopg2, and psycopg3 all do), orcustom_decodersactually dispatches to user code for this OID so the user can supply their own decoder.Impact
Any query that touches PostgreSQL system catalogs (
pg_type,pg_class,pg_attribute,pg_proc, …) will fail. The"char"type is extremely common in catalog tables —pg_typealone has five"char"columns (typtype,typcategory,typdelim,typalign,typstorage).Notes
"char"(OID 18) is distinct fromcharacter(n)/varchar(OID 1042 / 1043). It is a fixed-width single-byte internal type and should map directly to a one-character Pythonstr.