databendlabs/databend · error

linestring geometry

Error message

linestring geometry

What it means

In geographic overlay's `build_geometry_from_elements`, when all elements are `Geometry::LineString(_)`, each is converted with `try_into().expect("linestring geometry")` to build a MultiLineString. The preceding guard should make the conversion infallible; the panic indicates the LineString TryFrom impl rejected a guarded value — an invariant violation or malformed linestring from the overlay step.

Solutions

  1. Check overlay output linestrings for degenerate coordinate lists.
  2. Confirm geo crate version compatibility of the conversion impl.
  3. Replace expect with `.ok()`/`None` propagation consistent with the function's Option contract.

Example fix

// before
.map(|geo| geo.try_into().expect("linestring geometry"))
// after
.map(|geo| geo.try_into().ok())
.collect::<Option<Vec<_>>>()?;
Defensive patterns

Strategy: validation

Validate before calling

// before overlay:
let valid = geoms.iter().all(|g| matches!(g, Geometry::LineString(l) if l.coords().count() >= 2));

Type guard

fn is_valid_linestring(g: &Geometry) -> bool { matches!(g, Geometry::LineString(l) if l.coords().count() >= 2) }

Try / catch

let result = std::panic::catch_unwind(|| overlay(geoms.clone()));

Prevention

When it happens

Trigger: Overlay results composed entirely of linestrings where the `TryFrom<Geometry> for LineString<f64>` conversion fails — e.g. overlay-produced linestrings with too few points or invalid coordinate sequences.

Common situations: Overlaying adjacent polygons producing sliver linestrings; geo crate upgrades; precision artifacts generating degenerate lines.

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/7acd9f5eff5726f9. Report an issue: GitHub.

Appendix: source

Thrown at src/query/expression/src/geographic/overlay.rs:159

        if elements.is_empty() {
            return None;
        }

        if elements.iter().all(|geo| matches!(geo, Geometry::Point(_))) {
            let points: Vec<Point<f64>> = elements
                .into_iter()
                .map(|geo| geo.try_into().expect("point geometry"))
                .collect();
            return Some(Geometry::MultiPoint(MultiPoint::from_iter(points)));
        }

        if elements
            .iter()
            .all(|geo| matches!(geo, Geometry::LineString(_)))
        {
            let lines: Vec<LineString<f64>> = elements
                .into_iter()
                .map(|geo| geo.try_into().expect("linestring geometry"))
                .collect();
            return Some(Geometry::MultiLineString(MultiLineString::from_iter(lines)));
        }

        if elements
            .iter()
            .all(|geo| matches!(geo, Geometry::Polygon(_)))
        {
            let polygons: Vec<Polygon<f64>> = elements
                .into_iter()
                .map(|geo| geo.try_into().expect("polygon geometry"))
                .collect();
            return Some(Geometry::MultiPolygon(MultiPolygon::from_iter(polygons)));
        }

        Some(Geometry::GeometryCollection(GeometryCollection::from_iter(
            elements,
        )))

View on GitHub (pinned to 288d84d76e)