databendlabs/databend · error

polygon geometry

Error message

polygon geometry

What it means

In geographic aggregate `compute`, when all geometries are `Geometry::Polygon(_)`, each is converted to `Polygon<f64>` with `try_into().expect("polygon geometry")` to build a MultiPolygon. The type guard makes failure theoretically impossible, so this panic indicates the Polygon TryFrom impl rejected a guarded value — an internal invariant violation or bad polygon data.

Solutions

  1. Validate polygon inputs (non-empty exterior ring) before aggregation.
  2. Check geo crate version behavior of the Polygon TryFrom impl.
  3. Replace expect with error propagation so invalid polygons produce a query error.

Example fix

// before
.map(|geo| geo.try_into().expect("polygon geometry"))
// after
.map(|geo| geo.try_into().map_err(|e| ErrorCode::BadArguments(format!("polygon geometry: {e}"))))
.collect::<Result<Vec<_>, _>>()?;
Defensive patterns

Strategy: validation

Validate before calling

// caller-side check before aggregating:
let all_valid_polygons = geos.iter().all(|g| matches!(g, Geometry::Polygon(p) if !p.exterior().coords().is_empty()));

Type guard

fn has_valid_exterior(g: &Geometry) -> bool { matches!(g, Geometry::Polygon(p) if p.exterior().coords().count() >= 4) }

Try / catch

let result = std::panic::catch_unwind(|| aggregate_polygons(geos.clone()));

Prevention

When it happens

Trigger: Aggregating polygon geometries where the `TryFrom<Geometry> for Polygon<f64>` conversion fails despite the `Geometry::Polygon(_)` guard — e.g. polygons with empty exteriors or invalid ring data.

Common situations: Loading malformed polygons from external data; geo crate upgrades changing conversion semantics; corrupted geometry payloads.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/ecc2604c14f7a74a. Report an issue: GitHub.

Appendix: source

Thrown at src/query/expression/src/geographic/aggregate.rs:112

                .collect();
            let multi_point = MultiPoint::from_iter(points);
            return Ok(Some(Geometry::MultiPoint(multi_point)));
        }
        if geos
            .iter()
            .all(|geo| matches!(geo, Geometry::LineString(_)))
        {
            let lines: Vec<LineString<f64>> = geos
                .into_iter()
                .map(|geo| geo.try_into().expect("linestring geometry"))
                .collect();
            let multi_line_string = MultiLineString::from_iter(lines);
            return Ok(Some(Geometry::MultiLineString(multi_line_string)));
        }
        if geos.iter().all(|geo| matches!(geo, Geometry::Polygon(_))) {
            let polygons: Vec<Polygon<f64>> = geos
                .into_iter()
                .map(|geo| geo.try_into().expect("polygon geometry"))
                .collect();
            let multi_polygon = MultiPolygon::from_iter(polygons);
            return Ok(Some(Geometry::MultiPolygon(multi_polygon)));
        }

        let collection = GeometryCollection::from_iter(geos);
        Ok(Some(Geometry::GeometryCollection(collection)))
    }

    fn binary_compute(l_geo: Geometry<f64>, r_geo: Geometry<f64>) -> Result<Option<Geometry<f64>>> {
        Self::compute(vec![l_geo, r_geo])
    }
}

pub struct EnvelopeAggOp;

impl GeoAggOp for EnvelopeAggOp {
    fn compute(geos: Vec<Geometry<f64>>) -> Result<Option<Geometry<f64>>> {

View on GitHub (pinned to 288d84d76e)