Skip to content

[repo-health] Medium: serde Element enum fails on Overpass 'area' and 'count' element types #17

Description

@Liohtml

Summary

OverpassResponse.elements is deserialized from an internally-tagged serde enum that only knows three variants: node, way, relation. Overpass-QL supports two additional element types — area and count — that are returned by valid queries. Any query that produces an area or count element in the response will cause serde_json::from_str to return an unknown variant error, which propagates as Error::Json and causes OverpassClient::query() to fail entirely.

Category

Bug

Severity

Medium

Location

  • File: src/lib.rs
  • Line 191: #[serde(tag = "type", rename_all = "lowercase")]
  • Line 192: pub enum Element { Node { … }, Way { … }, Relation { … } }

Details

Two common query patterns trigger this:

  1. out count — counts matching elements without returning geometry or tags:

    [out:json];
    node["amenity"="cafe"]({{bbox}});
    out count;
    

    Response contains {"type": "count", "id": 0, "tags": {"nodes": "42"}}. serde returns Err("unknown variant \count`, expected one of `node`, `way`, `relation`")`.

  2. area queries — Overpass area elements are real map areas (different from way):

    [out:json];
    area["name"="Berlin"];
    out;
    

    Response elements have "type": "area", causing the same deserialization failure.

In both cases, the caller receives Error::Json(…) rather than partial results, making these perfectly valid query patterns unusable with the current client.

Suggested Fix

Add an #[serde(other)] catch-all variant to Element:

#[serde(tag = "type", rename_all = "lowercase")]
pub enum Element {
    Node { id: i64, #[serde(default)] lat: Option<f64>,},
    Way  { id: i64,},
    Relation { id: i64,},
    /// Catch-all for Overpass element types not yet modelled (e.g. `area`, `count`).
    /// These are silently skipped rather than causing a parse error.
    #[serde(other)]
    Unknown,
}

Note: #[serde(other)] on internally-tagged enums requires serde ≥ 1.0.135 and only works when the unknown variant has no fields. For a richer solution, use #[serde(untagged)] with a fallback struct that captures the raw JSON.

Effort Estimate

15 min


Automated finding by repo-health-agent v1.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions