risingwavelabs/risingwave · error
failed to convert struct to PostgreSQL point: expected…
Error message
failed to convert struct to PostgreSQL point: expected exactly two non-null float64 fields
What it means
When converting an RW Struct scalar into a PostgreSQL `point` adapter value, the struct must contain exactly two non-null Float64 fields (x, y) and nothing more. Wrong count, nulls, or non-float fields make the conversion fail. This is a strict shape contract for mapping RW structs onto Postgres point columns.
Solutions
- Ensure the mapped struct has exactly two fields, both Double/Float64 and non-null at runtime.
- Recreate/adjust the RW table so the struct is `struct<x double, y double>`.
- Cast numeric fields to double precision before conversion, or preprocess null coordinates.
- Project only the two coordinate fields in the sink's SELECT, dropping extras.
Example fix
// before: struct<a decimal, b decimal, id int> struct<a decimal, b decimal, id int> // after: exactly two double fields struct<x double, y double>
Defensive patterns
Strategy: type-guard
Validate before calling
fn is_valid_point_struct(s: &StructType) -> bool {
s.fields().len() == 2 && s.fields().iter().all(|f| f == &DataType::Float64)
} Type guard
fn is_point_compatible(fields: &[Option<ScalarRefImpl>]) -> bool {
matches!(fields,
[Some(Some(ScalarRefImpl::Float64(_))), Some(Some(ScalarRefImpl::Float64(_)))])
} Try / catch
match result {
Err(e) if e.to_string().contains("failed to convert struct to PostgreSQL point") => {
// fix struct shape to exactly two non-null float64 fields
}
other => other?,
} Prevention
- Declare point-mapped structs as exactly struct<x double, y double>.
- Coerce float32/decimal fields to double before the sink conversion.
- Filter out rows with null coordinates before writing.
- Project only the two coordinate fields; drop extras.
When it happens
Trigger: `ScalarAdapter::from_scalar` for the Point variant destructures the struct fields iterator expecting `(Some(Some(Float64)), Some(Some(Float64)), None)`; fires when the struct has missing fields, null x/y, non-Float64 fields (e.g. Float32/Decimal), or more than two fields.
Common situations: Sink mapping an RW struct with wrong field types onto a Postgres point column; struct fields declared as decimal or real instead of double; a struct with extra metadata fields mapped to a point; null coordinates in the data.
Related errors
- failed to convert PostgreSQL snapshot column
- failed to convert type
- ARRAY type missing element type
- bad result from postgres
- bad ssl root cert error
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/16d7414e97082a66.
Report an issue: GitHub.
Appendix: source
Thrown at src/connector/src/parser/scalar_adapter.rs:238
}
/// convert `ScalarRefImpl` to `ScalarAdapter` so that we can correctly encode to postgres value
pub(crate) fn from_scalar(
scalar: ScalarRefImpl<'_>,
ty: &Type,
) -> ConnectorResult<ScalarAdapter> {
Ok(match (scalar, ty, ty.kind()) {
(ScalarRefImpl::Utf8(s), &Type::UUID, _) => ScalarAdapter::Uuid(s.parse()?),
(ScalarRefImpl::Struct(point), &Type::POINT, _) => {
let mut fields = point.iter_fields_ref();
let (
Some(Some(ScalarRefImpl::Float64(x))),
Some(Some(ScalarRefImpl::Float64(y))),
None,
) = (fields.next(), fields.next(), fields.next())
else {
return Err(anyhow!(
"failed to convert struct to PostgreSQL point: expected exactly two non-null float64 fields"
)
.into());
};
ScalarAdapter::Point(PgPoint {
x: x.into_inner(),
y: y.into_inner(),
})
}
(ScalarRefImpl::Utf8(s), &Type::NUMERIC, _) => {
ScalarAdapter::Numeric(string_to_pg_numeric(s))
}
(ScalarRefImpl::Int256(s), &Type::NUMERIC, _) => {
ScalarAdapter::Numeric(string_to_pg_numeric(&s.to_string()))
}
(ScalarRefImpl::Utf8(s), _, Kind::Enum(_)) => {
ScalarAdapter::Enum(EnumString(s.to_owned()))View on GitHub (pinned to 6469eb736d)