louis-e/arnis · error

Earth has no PDS raster

Error message

Earth has no PDS raster

What it means

tile_name returns the PDS raster filename for a given celestial body's elevation band. Only Mars (banded files) and the Moon (single ldem_128.img file) have PDS rasters; Earth elevation is handled by a different provider path, so reaching tile_name with CelestialBody::Earth is a logic error and the code asserts this with unreachable!. Hitting this panic means Earth data was routed into the planetary (PDS) DEM pipeline.

Source

Thrown at src/elevation/providers/planetary.rs:97

        (self.lon_span * self.ppd as f64) as usize
    }

    /// File name for the tile whose band starts at `(lat_band_min, lon_band_min)`.
    fn tile_name(&self, body: CelestialBody, lat_band_min: f64, lon_band_min: f64) -> String {
        let lat_band_max = lat_band_min + self.lat_span;
        match body {
            // megt{max_lat}{n|s}{lon:03}hb.img, label is MAXIMUM_LATITUDE.
            CelestialBody::Mars => {
                let hemi = if lat_band_max >= 0.0 { 'n' } else { 's' };
                format!(
                    "megt{:02}{hemi}{:03}hb.img",
                    lat_band_max.abs() as i32,
                    lon_band_min as i32
                )
            }
            // One global file, so the band arguments are always the full globe.
            CelestialBody::Moon => "ldem_128.img".to_string(),
            CelestialBody::Earth => unreachable!("Earth has no PDS raster"),
        }
    }
}

pub struct PlanetaryDem {
    pub body: CelestialBody,
}

impl ElevationProvider for PlanetaryDem {
    fn name(&self) -> &'static str {
        match self.body {
            CelestialBody::Moon => "lola",
            CelestialBody::Mars => "mola",
            CelestialBody::Earth => "planetary",
        }
    }

    fn coverage_bboxes(&self) -> Option<Vec<LLBBox>> {

View on GitHub (pinned to 34048924d9)

Solutions

  1. Use the Earth-specific elevation provider (e.g. the fixed-tile/SRTM path) instead of PlanetaryDem when body is Earth.
  2. Add an explicit guard at PlanetaryDem construction that rejects CelestialBody::Earth with a clear error, so the failure surfaces at setup rather than mid-fetch.
  3. Fix the body/provider dispatch so Earth requests never route to the PDS pipeline.

Example fix

// before
let dem = PlanetaryDem { body: CelestialBody::Earth };
dem.fetch_row(...); // panics: unreachable
// after
match body {
    CelestialBody::Earth => earth_provider.fetch(...),
    CelestialBody::Mars | CelestialBody::Moon => PlanetaryDem { body }.fetch_row(...),
}
Defensive patterns

Strategy: validation

Validate before calling

if dem.body === 'Earth') throw new Error('PlanetaryDem does not support Earth; use the Earth elevation provider');

Type guard

fn is_pds_supported(body: &CelestialBody) -> bool {
    matches!(body, CelestialBody::Mars | CelestialBody::Moon)
}

Try / catch

// Rust panic; guard upstream instead
assert!(is_pds_supported(&dem.body), "PlanetaryDem requires Mars or Moon");
let row = dem.fetch_row(...);

Prevention

When it happens

Trigger: Calling fetch_row on a PlanetaryDem whose body is CelestialBody::Earth; constructing a PlanetaryDem with body = Earth and then invoking any fetch path that resolves a PDS tile name.

Common situations: Config or body-selection code defaulting to Earth but instantiating the planetary provider instead of the Earth provider; a body enum parsed from user input ('earth') reaching the wrong provider; a dispatch table that lists Earth as supported for planetary DEMs.

Related errors


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