{"record":{"id":"e9b30c15b2477dcb","repo":"risingwavelabs/risingwave","slug":"failed-to-convert-type-to-scalaradapter","errorCode":null,"errorMessage":"failed to convert type {:?} to ScalarAdapter","messagePattern":"failed to convert type (.+?) to ScalarAdapter","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/parser/scalar_adapter.rs","lineNumber":191,"sourceCode":"    ) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {\n        match ty.kind() {\n            Kind::Simple => match *ty {\n                Type::UUID => Ok(ScalarAdapter::Uuid(uuid::Uuid::from_sql(ty, raw)?)),\n                Type::POINT => Ok(ScalarAdapter::Point(PgPoint::from_sql(ty, raw)?)),\n                // In order to cover the decimal beyond RustDecimal(only 28 digits are supported),\n                // we use the PgNumeric to handle decimal from postgres.\n                Type::NUMERIC => Ok(ScalarAdapter::Numeric(PgNumeric::from_sql(ty, raw)?)),\n                _ => Ok(ScalarAdapter::Builtin(ScalarImpl::from_sql(ty, raw)?)),\n            },\n            Kind::Enum(_) => Ok(ScalarAdapter::Enum(EnumString::from_sql(ty, raw)?)),\n            Kind::Array(Type::NUMERIC) => {\n                Ok(ScalarAdapter::NumericList(FromSql::from_sql(ty, raw)?))\n            }\n            Kind::Array(inner_type) if let Kind::Enum(_) = inner_type.kind() => {\n                Ok(ScalarAdapter::EnumList(FromSql::from_sql(ty, raw)?))\n            }\n            Kind::Array(_) => Ok(ScalarAdapter::List(FromSql::from_sql(ty, raw)?)),\n            _ => Err(anyhow!(\"failed to convert type {:?} to ScalarAdapter\", ty).into()),\n        }\n    }\n\n    fn accepts(ty: &Type) -> bool {\n        match ty.kind() {\n            Kind::Simple => {\n                matches!(ty, &Type::UUID | &Type::NUMERIC | &Type::POINT)\n                    || <ScalarImpl as FromSql>::accepts(ty)\n            }\n            Kind::Enum(_) => true,\n            Kind::Array(inner_type) => <ScalarAdapter as FromSql>::accepts(inner_type),\n            _ => false,\n        }\n    }\n}\n\nimpl ScalarAdapter {\n    pub fn name(&self) -> &'static str {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/parser/scalar_adapter.rs#L173-L209","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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`.","solutions":["Identify the reported Postgres type and change the RW column to a supported equivalent (e.g. cast composite to text/JSON).","Cast the column in the snapshot read query (e.g. `col::text`) to a decodable type.","Avoid custom/composite Postgres types in columns synced to RisingWave; use JSON instead.","Upgrade RisingWave if support was added later, or file an issue."],"exampleFix":"-- before: RW reads a composite column directly\nSELECT info FROM users;\n-- after\nSELECT info::text AS info FROM users; -- declare as varchar in RW","handlingStrategy":"validation","validationCode":"-- List PG column kinds that will reach the adapter and ensure they are simple/array:\nSELECT column_name, udt_name FROM information_schema.columns\nWHERE table_name = 'my_table'\nAND udt_name NOT IN ('int2','int4','int8','float4','float8','numeric','text','varchar','bool');","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"failed to convert type\") => {\n        // cast the offending PG column to text in the source query\n    }\n    other => other?,\n}","preventionTips":["Avoid composite/range/custom PG types in synced columns; prefer JSON-as-text.","Cast exotic types in the snapshot SELECT statement.","Keep PG schemas stable during snapshot reads."],"tags":["postgres","type-conversion","unsupported-type","cdc"],"backgroundTag":"unsupported-enum-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}