← Blog

Build Log #014: Four Parcels in Michigan Broke Every Search in America

A user searched for coordinates in DMS format. Nothing came back. The bug wasn't in the parser — it was four parcels with NaN geometries that poisoned every spatial query in the entire database. Across all 50 states.

Build logs are our honest engineering journal. Not the polished case study — the messy, frustrating, "why is this broken" reality of building production geospatial AI systems.

The Bug Report

A user searched for a location using DMS coordinates — something like 46°48'00.9"N 101°47'17.6"W. No results. Blank page. The search bar just sat there, mocking us.

Our platform handles millions of parcels across all 50 states. DMS coordinate search is a bread-and-butter feature for anyone who works with land — surveyors, appraisers, real estate analysts. If it doesn't work, we're dead.

First instinct: the DMS parser is broken. We'd recently added it, and parsing degree-minute-second notation with all its Unicode characters, directional suffixes, and delimiter variations is the kind of thing that breaks in creative ways.

We tested the regex. It parsed correctly. 46°48'00.9"N became 46.80025, 101°47'17.6"W became -101.78822. Perfect conversion. The parser was fine.

So why were we getting zero results?

Down the Rabbit Hole: North Dakota

The coordinates pointed to North Dakota. We ran the spatial query manually in psql:

SELECT COUNT(*) FROM parcels
WHERE state = 'ND'
AND geom && ST_MakeEnvelope(-101.80, 46.79, -101.77, 46.81, 4326);

Zero rows. But we knew there were parcels there — we'd ingested the full North Dakota dataset. Something was wrong with the geometries themselves.

SELECT COUNT(*) FROM parcels
WHERE state = 'ND' AND NOT ST_IsValid(geom);

12,814 invalid geometries.

Twelve thousand parcels with unclosed polygon rings. This is a classic GIS data quality issue — the source data has polygons where the last vertex doesn't quite connect back to the first. PostGIS is strict about this. If the ring isn't closed, the geometry is invalid, and spatial operations on it are undefined.

Easy fix:

UPDATE parcels
SET geom = ST_MakeValid(geom)
WHERE state = 'ND' AND NOT ST_IsValid(geom);

12,814 rows updated. We ran the search again.

Still broken.

Wait. Not "still broken" — broken differently. Now the query returned results, but it also returned parcels from completely wrong states. A search in North Dakota was pulling back parcels from Michigan, Idaho, and Florida. The bounding box query was matching parcels that couldn't possibly be within a 0.03-degree envelope in rural North Dakota.

That's when things got weird.

The Poison Pills

We dug into the Michigan parcels that were showing up in a North Dakota search. Specifically, we looked at their bounding boxes:

SELECT id, ST_XMin(geom), ST_YMin(geom), ST_XMax(geom), ST_YMax(geom)
FROM parcels
WHERE state = 'MI' AND id IN (...);

The output:

 id  | st_xmin | st_ymin | st_xmax | st_ymax
-----+---------+---------+---------+---------
 ... |     NaN |     NaN |     NaN |     NaN
 ... |     NaN |     NaN |     NaN |     NaN
 ... |     NaN |     NaN |     NaN |     NaN
 ... |     NaN |     NaN |     NaN |     NaN

NaN. Not a Number. Four parcels in Michigan had geometries where every coordinate was NaN.

Here's the thing about NaN that makes it terrifying in spatial databases: NaN satisfies every comparison. In IEEE 754 floating point, NaN isn't less than anything and isn't greater than anything, but PostGIS's bounding box operator (&&) uses a range-intersection test. A NaN bounding box intersects with everything.

Every spatial query we ran — for any coordinate, in any state, anywhere in America — matched these four Michigan parcels. They were phantom results contaminating every search. And when the query tried to do any further geometry operation on them (like ST_Contains or ST_Intersects), PostGIS crashed with an internal error.

Four parcels. Four NaN geometries. Breaking every search in the database.

The Wrong Fix We Almost Shipped

Here's the embarrassing part. In an earlier debugging session, we'd noticed invalid geometries causing issues and added ST_IsValid(geom) filters to our geocode service:

WHERE ST_IsValid(geom) AND geom && search_envelope

This "fixed" the bug by excluding all invalid parcels from results. But it was the wrong fix. We were throwing away thousands of perfectly queryable parcels just because they had minor validity issues like unclosed rings. Those parcels had real data — owner names, acreage, zoning classifications — that users needed.

The right approach: fix the data, don't filter it. We ripped out every ST_IsValid(geom) filter and replaced them with ST_MakeValid(geom) in the SELECT clauses:

SELECT ST_MakeValid(geom) as geom, owner, acreage, ...
FROM parcels
WHERE geom && search_envelope;

This repairs geometries on-the-fly during query execution. Minor issues like unclosed rings get fixed transparently. The parcel data still comes back. Users never know the source data was imperfect.

For the four NaN parcels specifically, there was nothing to repair — their geometries were pure garbage. We nulled them out:

UPDATE parcels SET geom = NULL
WHERE state = 'MI'
AND ST_XMin(geom)::text = 'NaN';

Then we ran ST_MakeValid across the remaining 23,000+ invalid Michigan geometries for good measure.

The Aftermath

After the fix, we tested DMS coordinate searches across a dozen states. Clean results every time. The correct parcels, in the correct state, with the correct metadata. No phantom Michigan parcels appearing in North Dakota searches.

We rebuilt the API, cleared the cache, and let it rip.

What We Learned

Three things, in decreasing order of humility:

1. NaN geometries in PostGIS are poison pills. They match every bounding box query. They don't just break the state they're in — they break every state. If you're ingesting geospatial data from external sources (county assessor offices, state GIS portals, USDA datasets), scan for NaN coordinates on ingest. Don't wait for a user to find them.

2. Don't filter bad data when you can fix it. Our first instinct — WHERE ST_IsValid(geom) — was a band-aid that silently dropped valid parcels from search results. ST_MakeValid repairs the geometry while preserving the data. Filtering is hiding; fixing is engineering.

3. The bug is never where you think it is. We started at the DMS parser. The parser was perfect. The real bug was in four rows out of 4.09 million Michigan parcels that happened to have NaN coordinates — data that had been sitting in our database since the initial ingest, waiting to ruin someone's day.

Four parcels. Fifty states broken. Sometimes the smallest data quality issues have the largest blast radius.


This is Build Log #014. We publish these as we build — the real engineering stories behind production geospatial AI systems. If you're working with spatial data at scale and want to talk about data quality pipelines, get in touch.