risingwavelabs/risingwave · error

failed to convert type {:?} to ScalarAdapter

Error message

failed to convert type {:?} to ScalarAdapter

What it means

ScalarAdapter's Postgres `FromSql` implementation handles simple types, arrays of numerics, arrays of enums, and plain arrays; any other Postgres Kind reaching `from_sql` cannot be represented and errors with the offending Postgres type name. It is the low-level guard for unsupported PG wire types.

Source

Thrown at src/connector/src/parser/scalar_adapter.rs:191

    ) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
        match ty.kind() {
            Kind::Simple => match *ty {
                Type::UUID => Ok(ScalarAdapter::Uuid(uuid::Uuid::from_sql(ty, raw)?)),
                Type::POINT => Ok(ScalarAdapter::Point(PgPoint::from_sql(ty, raw)?)),
                // In order to cover the decimal beyond RustDecimal(only 28 digits are supported),
                // we use the PgNumeric to handle decimal from postgres.
                Type::NUMERIC => Ok(ScalarAdapter::Numeric(PgNumeric::from_sql(ty, raw)?)),
                _ => Ok(ScalarAdapter::Builtin(ScalarImpl::from_sql(ty, raw)?)),
            },
            Kind::Enum(_) => Ok(ScalarAdapter::Enum(EnumString::from_sql(ty, raw)?)),
            Kind::Array(Type::NUMERIC) => {
                Ok(ScalarAdapter::NumericList(FromSql::from_sql(ty, raw)?))
            }
            Kind::Array(inner_type) if let Kind::Enum(_) = inner_type.kind() => {
                Ok(ScalarAdapter::EnumList(FromSql::from_sql(ty, raw)?))
            }
            Kind::Array(_) => Ok(ScalarAdapter::List(FromSql::from_sql(ty, raw)?)),
            _ => Err(anyhow!("failed to convert type {:?} to ScalarAdapter", ty).into()),
        }
    }

    fn accepts(ty: &Type) -> bool {
        match ty.kind() {
            Kind::Simple => {
                matches!(ty, &Type::UUID | &Type::NUMERIC | &Type::POINT)
                    || <ScalarImpl as FromSql>::accepts(ty)
            }
            Kind::Enum(_) => true,
            Kind::Array(inner_type) => <ScalarAdapter as FromSql>::accepts(inner_type),
            _ => false,
        }
    }
}

impl ScalarAdapter {
    pub fn name(&self) -> &'static str {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Identify the reported Postgres type and change the RW column to a supported equivalent (e.g. cast composite to text/JSON).
  2. Cast the column in the snapshot read query (e.g. `col::text`) to a decodable type.
  3. Avoid custom/composite Postgres types in columns synced to RisingWave; use JSON instead.
  4. Upgrade RisingWave if support was added later, or file an issue.

Example fix

-- before: RW reads a composite column directly
SELECT info FROM users;
-- after
SELECT info::text AS info FROM users; -- declare as varchar in RW
Defensive patterns

Strategy: validation

Validate before calling

-- List PG column kinds that will reach the adapter and ensure they are simple/array:
SELECT column_name, udt_name FROM information_schema.columns
WHERE table_name = 'my_table'
AND udt_name NOT IN ('int2','int4','int8','float4','float8','numeric','text','varchar','bool');

Try / catch

match result {
    Err(e) if e.to_string().contains("failed to convert type") => {
        // cast the offending PG column to text in the source query
    }
    other => other?,
}

Prevention

When it happens

Trigger: `ScalarAdapter::from_sql` is called on the tokio-postgres row decoding path (used by the Postgres CDC snapshot reader) when the column's Postgres `Kind` is not Simple or a handled Array kind — e.g. composite, range, or pseudo types reaching the adapter.

Common situations: A Postgres composite/range/custom-domain column mapped into an RW column the adapter cannot decode; a new Postgres type not yet in the adapter's accept list; schema drift after `ALTER TABLE ... TYPE`.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/e9b30c15b2477dcb. Report an issue: GitHub.