louis-e/arnis · error

Error in defining coordinate transformation: {e}

Error message

Error in defining coordinate transformation:
{e}

What it means

parse_osm_data builds a CoordTransformer via llbbox_to_xzbbox (or a variant) to convert lat/lon bounding boxes into Minecraft x/z coordinates. If the coordinate transformation cannot be defined — the underlying proj/geodesic computation fails or the resulting transform is invalid — the Result is Err and the code deliberately panics with 'Error in defining coordinate transformation:\n{e}'. It panics instead of exiting because the GUI invokes this from a Tauri blocking task, where process::exit would kill the whole app; invalid scales are rejected earlier by validate_scale.

Source

Thrown at src/osm_parser.rs:834

    // Deserialize the JSON data into the OSMData structure
    let data = SplitOsmData::from_raw_osm_data(osm_data);

    let (coord_transformer, xzbbox) = match projection {
        crate::projection::ProjectionKind::WebMercator => {
            let origin_lat = (bbox.min().lat() + bbox.max().lat()) / 2.0;
            let origin_lon = (bbox.min().lng() + bbox.max().lng()) / 2.0;
            let proj = crate::projection::WebMercatorProjection::new(origin_lat, origin_lon, scale);
            CoordTransformer::with_projection(&bbox, scale, &proj)
        }
        crate::projection::ProjectionKind::Local => {
            CoordTransformer::llbbox_to_xzbbox(&bbox, scale)
        }
    }
    // Panics rather than exits: the GUI calls this from a Tauri blocking task, where an
    // exit would take the whole app down. Bad scales are rejected up front by validate_scale.
    .unwrap_or_else(|e| {
        panic!("Error in defining coordinate transformation:\n{e}");
    });

    if debug {
        println!("Total elements: {}", data.total_count());
        println!("Scale factor X: {}", coord_transformer.scale_factor_x());
        println!("Scale factor Z: {}", coord_transformer.scale_factor_z());
    }

    let mut part_groups = PartGroups::new();
    let mut outline_suppression =
        compute_outline_suppression(&data.relations, &data.ways, &data.nodes, &mut part_groups);
    // Ways owned by a type=building relation are handled above; the spatial pass must
    // not re-judge them against unrelated parts that merely fall inside their footprint.
    let relation_ways: HashSet<u64> = data
        .relations
        .iter()
        .filter(|r| {
            r.tags

View on GitHub (pinned to 34048924d9)

Solutions

  1. Validate the bbox before calling: min_lat < max_lat, min_lon < max_lon, all values finite, lat within [-90,90], lon within [-180,180]
  2. Run validate_scale on the scale argument first (the parser assumes it was already applied)
  3. Check the panic message's {e} body — it contains the underlying transformer error naming the bad parameter
  4. Sanitize/parse bbox input strictly (reject NaN, inf, non-numeric tokens) at the CLI/GUI boundary
  5. If hit from the GUI, the panic is caught by the Tauri blocking-task handling; report and fix the input values that were passed in

Example fix

// before: unvalidated input from user string
let bbox = parse_bbox(&args.bbox).unwrap();
osm_parser::parse_osm_data(&data, &bbox, scale, debug);
// after: validate before transforming
let bbox = parse_bbox(&args.bbox)?;
assert!(bbox.min_lat < bbox.max_lat && bbox.min_lon < bbox.max_lon,
        "bbox must be min,max ordered and finite");
validate_scale(scale)?;
osm_parser::parse_osm_data(&data, &bbox, scale, debug);
Defensive patterns

Strategy: validation

Validate before calling

fn bbox_is_valid(bbox: &LLBBox) -> bool {
    bbox.min_lat < bbox.max_lat
        && bbox.min_lon < bbox.max_lon
        && bbox.min_lat >= -90.0 && bbox.max_lat <= 90.0
        && bbox.min_lon >= -180.0 && bbox.max_lon <= 180.0
        && [bbox.min_lat, bbox.max_lat, bbox.min_lon, bbox.max_lon]
            .iter().all(|v| v.is_finite())
}
// also: validate_scale(scale)?; before calling parse_osm_data

Try / catch

// Rust: catch the panic when calling from the GUI blocking task
let result = std::panic::catch_unwind(|| {
    osm_parser::parse_osm_data(&data, &bbox, scale, debug)
});
match result {
    Ok(parsed) => parsed,
    Err(p) => emit_gui_error("Invalid bbox/scale: coordinate transform failed")
}

Prevention

When it happens

Trigger: Calling parse_osm_data with a bbox that produces a degenerate/invalid transform (zero-size or inverted min/max coordinates, coordinates outside valid lat/lon ranges like lat > 90 or NaN), or with values that slip past validate_scale (e.g. calling the API directly from the GUI command without validating scale first).

Common situations: Hand-edited or GUI-supplied bbox strings like "a,b,c,d" partially parsed into weird floats; swapped min/max lat/lon yielding a negative-size box; programmatically generated bboxes containing NaN/inf; calling the library path directly and skipping validate_scale.

Related errors


AI-assisted analysis of louis-e/arnis@34048924d9 (2026-09-03). Data as JSON: /api/errors/314f64143aaecdea. Report an issue: GitHub.