louis-e/arnis · error · Error
land cover grid mismatch
Error message
land cover grid mismatch
What it means
The land cover payload ('APL1') carries its own grid dimensions (gw, gh) in its header; this check asserts they match the DEM dataset's grid (d.gw, d.gh) because the land cover raster is overlaid pixel-for-pixel on the DEM grid. A mismatch means the two rasters cannot be aligned, so the overlay is aborted with this Error.
Source
Thrown at src/gui/js/preview3d.js:414
if (!modalView || !modalView.map) return;
const map = modalView.map;
try {
if (map.getLayer("landcover")) {
map.setLayoutProperty("landcover", "visibility", enabled ? "visible" : "none");
return;
}
if (!enabled) return;
const d = datasets.get(modalView.gen);
if (!d) return;
toggle.disabled = true;
let url = landCoverCache.key === d.bboxText ? landCoverCache.url : null;
if (!url) {
const raw = await window.__TAURI__.core.invoke("gui_get_preview_landcover", {
bboxText: d.bboxText,
});
const { buffer, gw, gh } = readPayloadHeader(raw, "APL1");
if (gw !== d.gw || gh !== d.gh) throw new Error("land cover grid mismatch");
url = landCoverUrl(new Uint8Array(buffer, 12, gw * gh), gw, gh);
landCoverCache = { key: d.bboxText, url: url };
}
if (!modalView || modalView.map !== map) return;
map.addSource("landcover", {
type: "image",
url: url,
coordinates: [
[d.minLng, d.maxLat],
[d.maxLng, d.maxLat],
[d.maxLng, d.minLat],
[d.minLng, d.minLat],
],
});
map.addLayer(
{
id: "landcover",
type: "raster",View on GitHub (pinned to 34048924d9)
Solutions
- Make the Rust gui_get_preview_landcover command derive its grid dimensions from the same source as the DEM command so gw/gh always match d.gw/d.gh.
- Capture the dataset generation/id when starting the land cover fetch and re-validate (or discard) the result if the dataset changed while awaiting.
- Invalidate landCoverCache whenever the DEM dataset is regenerated, not only when bboxText changes.
- Catch this error in the caller and retry the land cover fetch once after refreshing the dataset dimensions.
- Log gw/gh from both payloads on mismatch to quickly identify which side's resolution constant drifted.
Example fix
// before
const raw = await window.__TAURI__.core.invoke("gui_get_preview_landcover", { bboxText: d.bboxText });
const { buffer, gw, gh } = readPayloadHeader(raw, "APL1");
if (gw !== d.gw || gh !== d.gh) throw new Error("land cover grid mismatch");
// after
const genAtStart = d.gen;
const raw = await window.__TAURI__.core.invoke("gui_get_preview_landcover", { bboxText: d.bboxText });
if (d.gen !== genAtStart) return; // dataset regenerated mid-flight
const { buffer, gw, gh } = readPayloadHeader(raw, "APL1");
if (gw !== d.gw || gh !== d.gh) {
console.error("landcover grid", gw, gh, "vs dem", d.gw, d.gh);
landCoverCache = { key: null, url: null };
return;
} Defensive patterns
Strategy: validation
Validate before calling
const { buffer, gw, gh } = readPayloadHeader(raw, "APL1");
if (gw !== d.gw || gh !== d.gh) {
console.error("landcover dims", { gw, gh, demGw: d.gw, demGh: d.gh });
return; // skip overlay instead of throwing
} Type guard
function dimsMatch(cover, dem) { return cover.gw === dem.gw && cover.gh === dem.gh; } Try / catch
try {
await loadLandCover(d);
} catch (e) {
if (e.message === "land cover grid mismatch") {
landCoverCache = { key: null, url: null };
return; // render terrain without overlay
}
throw e;
} Prevention
- Derive land cover and DEM grid dimensions from one shared constant in the Rust backend.
- Use a generation token and re-validate the dataset after every await.
- Clear landCoverCache whenever the DEM is regenerated, not only on bbox change.
- Log both grids' dimensions on mismatch to spot which side drifted.
When it happens
Trigger: Calling gui_get_preview_landcover with the dataset's bboxText and receiving a grid whose width/height differ from d.gw/d.gh — e.g. the Rust backend computes land cover at a different resolution, the bbox text maps to a different cached grid, or the DEM dataset was regenerated at a new resolution while landCoverCache still holds a result keyed to the old bboxText but the newly fetched cover uses old dims (or vice versa).
Common situations: Backend changed its land cover resolution constant without a matching change to the DEM grid size; user panned/resized the selection so bboxText changed and the DEM was re-fetched at new dims while a stale land cover response arrived for the old dims; concurrent generations interleaving async results (no generation token checked before the dimension comparison).
Related errors
- Unexpected preview payload format
- No preview data available
- Failed to get main window
- Error while starting the application UI (Tauri)
AI-assisted analysis of louis-e/arnis@34048924d9 (2026-09-03).
Data as JSON: /api/errors/8f9ff4682c7a9b27.
Report an issue: GitHub.