a-b-street/abstreet · error
Malformed coordinates
Error message
Malformed coordinates: {} What it means
While recursing through KML, each <coordinates> element is parsed as space/comma-separated lon,lat pairs. When any pair fails to parse (wrong number of components or non-numeric text), recurse bails with the offending pair included in the message.
Solutions
- Open the KML, find the pair printed in the error, and fix or remove it — coordinates must be numeric lon,lat (optionally alt) triples like '-1.2,54.5,0'.
- Normalize the file: replace locale decimal commas with dots and strip empty tokens before loading.
- If the file comes from an external tool, re-export it with plain 2D WGS84 coordinates.
Example fix
// before (KML coordinates) -1.2,54.5,0 -1,3,54,6 // after -1.2,54.5,0 -1.3,54.6,0
Defensive patterns
Strategy: validation
Validate before calling
for pair in coords_text.split_whitespace() {
let parts: Vec<&str> = pair.split(',').collect();
if !(2..=3).contains(&parts.len()) || parts.iter().any(|p| p.parse::<f64>().is_err()) {
bail!("Malformed coordinates: {}", pair);
}
} Type guard
fn is_valid_coord_pair(pair: &str) -> bool {
pair.split(',').map(str::trim).filter(|p| !p.is_empty())
.take(2).count() >= 2
&& pair.split(',').take(2).all(|p| p.trim().parse::<f64>().is_ok())
} Try / catch
match load_kml(path, ...) {
Ok(shapes) => shapes,
Err(e) if e.to_string().starts_with("Malformed coordinates") => {
eprintln!("Fix the KML coordinate pair: {e}");
return Err(e);
}
Err(e) => return Err(e),
} Prevention
- Prefer 2D lon,lat coordinates and consistent dot decimal separators in KML
- Lint KML files with an XML/coordinates checker before loading
- Avoid hand-editing coordinates; re-export from the source tool
When it happens
Trigger: Loading a KML file whose Placemark coordinates contain malformed entries — e.g. 'lat,lon,alt,extra', 'x,y' with non-numeric values, doubled commas, or newline-only junk between valid pairs.
Common situations: Hand-edited KML; KML exported by tools that emit 3D coordinates or locale-formatted decimals (comma decimal separators); copy-pasted coordinate strings with stray characters.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/10ff571aeaabd392.
Report an issue: GitHub.
Appendix: source
Thrown at kml/src/lib.rs:113
.text()
.map(|x| x.to_string())
.unwrap_or_else(String::new);
kv.insert(key, value);
} else if node.tag_name().name() == "coordinates" {
let mut any_oob = false;
let mut any_ok = false;
let mut pts: Vec<LonLat> = Vec::new();
if let Some(txt) = node.text() {
for pair in txt.trim().split(' ') {
if let Some(pt) = parse_pt(pair) {
pts.push(pt);
if gps_bounds.contains(pt) {
any_ok = true;
} else {
any_oob = true;
}
} else {
bail!("Malformed coordinates: {}", pair);
}
}
}
if any_ok && (!any_oob || !require_all_pts_in_bounds) {
let attributes = std::mem::take(kv);
shapes.push(ExtraShape {
points: pts,
attributes,
});
} else {
*skipped_count += 1;
}
}
Ok(())
}
fn parse_pt(input: &str) -> Option<LonLat> {
let coords: Vec<&str> = input.split(',').collect();View on GitHub (pinned to 0964f29315)