A pair of numbers is not a location. It becomes a location only when something states what the numbers are measured against: which model of the Earth's shape, which origin, which units, and in which order the two values are written. That statement is the coordinate reference system, and when it is missing or wrong, the numbers still look completely normal.
That is the whole difficulty. A corrupted image looks corrupted. A coordinate in the wrong reference system looks like a coordinate. It has the right number of decimal places, it sits in a plausible numeric range, it serializes cleanly, and it passes every schema check. It just refers to a different piece of the planet than the one intended, sometimes by a few meters and sometimes by several thousand kilometers.
Most spatial bugs that survive to production are of this kind. They are not logic errors. They are unit errors, in a domain where the units are complicated enough that entire libraries exist to convert between them, and where the conversion is frequently skipped because the numbers already looked fine.
What a coordinate reference system actually specifies
A CRS is a bundle of decisions, and knowing which decisions are in the bundle makes the failure modes predictable.
- A datum, which fixes the origin and orientation of the coordinate frame relative to the physical Earth. This is the part people skip, and it is the part that produces silent offsets.
- An ellipsoid, the mathematical surface that approximates the Earth's shape, with its own radius and flattening. Different ellipsoids fit different regions better, which is why so many exist.
- A prime meridian, almost always Greenwich now, occasionally not in historic data.
- Units, degrees for angular systems, meters or feet for planar ones. Survey feet and international feet are not the same, and the difference is small enough to be invisible at a glance and large enough to matter over a long baseline.
- A projection, if the system is planar, along with its parameters: the central meridian, the standard parallels, the false easting and northing, the scale factor.
Systems are usually referenced by a numeric code from a registry rather than described in full, which is efficient and also means most people never read what they are using. The code identifies the whole bundle. Two datasets carrying different codes cannot be overlaid until one is transformed to the other, and doing that transformation correctly requires knowing the datum relationship, not just the projection.
Geographic against projected
A geographic system stores latitude and longitude as angles on an ellipsoid. It covers the entire planet in one continuous frame, has no seams except at the antimeridian, and is the right way to store and exchange data.
The trap is that a degree is not a distance. A degree of latitude is roughly constant. A degree of longitude shrinks from its maximum at the equator to nothing at the poles. Treating latitude and longitude as if they were planar x and y produces a distance calculation that is wrong everywhere except near the equator, and the error grows with latitude. Any pipeline computing lengths, areas, or buffers directly on degrees is producing numbers that vary in meaning with the position of the data.
A projected system stores coordinates on a plane in linear units. Within its intended zone it supports ordinary geometry: the distance between two points is the Euclidean distance, an area is an area, a buffer is a circle. Outside its intended zone the distortion grows quickly, which is the reason there are thousands of projected systems rather than one.
The working rule is straightforward. Store and exchange in a geographic system. Project into an appropriate local system for measurement. Project back for storage. Do not measure in whatever the data happened to arrive in, and do not store in a local projected system if the data will ever leave its zone.
The web mapping projection, and the cost of computing in it
Essentially every online slippy map uses one projection, a variant of Mercator applied to a spherical model of the Earth. It became the default for good engineering reasons: it is conformal, so shapes look right locally and north is always up; it maps the world onto a square that subdivides cleanly into a quadtree of tiles; and the math is cheap.
Its defect is area. Mercator stretches area by a factor that grows with latitude, and the growth is severe. Near the equator the distortion is negligible. In the mid latitudes, features appear substantially larger than they are. Toward the poles the exaggeration becomes extreme, which is why the familiar world map makes high latitude landmasses look comparable to entire continents.
For display this is a known trade and mostly harmless. For computation it is corrosive, because the error is not a fixed offset that can be corrected once. It is a multiplier that depends on where the geometry sits. Two polygons of identical true area, one at low latitude and one at high latitude, have different areas when measured in this projection. A pipeline that computes area in web Mercator has produced a result where geography is confounded with the measurement error, and no single correction factor fixes it.
The same applies to distances, buffers, and any density computed as a count over an area. A buffer of a fixed number of projected units is a different real world distance in different places. A density map computed this way understates density at high latitudes, systematically, in a pattern that looks like a real geographic gradient.
There is a further wrinkle: the web projection is defined on a sphere while the underlying coordinates are on an ellipsoid. This mismatch is a deliberate simplification that keeps tile math simple, and it introduces a small latitude dependent shift that is irrelevant for map display and not irrelevant for precise work.
The rule that avoids all of it: use the web projection to draw pixels, never to derive a number.
Datum shifts, the error that survives sanity checks
Datum problems are the most dangerous category because they produce results that pass every plausibility test.
Two coordinates can share the same latitude and longitude values and refer to points hundreds of meters apart if they are expressed against different datums. A global datum and a regional datum place their reference frames differently, because a regional datum was fitted to give the best local match at the expense of global consistency. A dataset produced against a national grid and reprojected without a datum transformation will land near, but not on, its true position.
Nothing about this looks broken. The point is in the right country, the right city, usually the right neighborhood. It falls on land. It is inside the correct administrative polygon most of the time. It just sits in the wrong place by an amount large enough to put a building on the neighboring parcel, a well on the wrong side of a lease boundary, or an asset in the wrong flood zone.
There is a second flavor of the same problem, and it is growing. Continental plates move, at rates on the order of centimeters per year. A frame fixed to a plate keeps coordinates stable for local users while drifting from a global frame. Over a couple of decades this accumulates to something visible in high accuracy work, which is why some national systems are tied to a specific epoch and why merging survey data from different decades without accounting for the epoch produces a slow, systematic disagreement.
The mitigation is a matter of discipline more than technology. Record the datum as part of every coordinate, not just the projection. Use a transformation library that applies a datum shift rather than a bare change of projection parameters. When precision matters, record the epoch. When two datasets disagree by a consistent offset in a consistent direction, suspect the datum before suspecting the data.
Axis order, the bug that flips hemispheres
The order of the two numbers is not universally agreed. Mathematical and cartographic convention says x then y, which means longitude then latitude. Geodetic authorities define many geographic systems as latitude then longitude, and standards bodies have taken different positions at different times, with some service versions swapping the order relative to earlier versions of the same service.
The practical result is that the same file, the same registry code, and the same standard can produce opposite interpretations in two libraries. GeoJSON settled the question for itself by mandating longitude first, which is a genuine improvement, and a great deal of data still arrives from systems that use the opposite convention.
The failure is loud when the values are unambiguous. A latitude of 106 is impossible, so a swapped pair involving a longitude beyond 90 will usually blow up or produce an obviously absurd result. The failure is silent and much worse when both values are in valid latitude range. A point at 6 south and 39 east near the East African coast, swapped, becomes 39 north 6 east, in southern Europe. Both are legal coordinates. Both are on land. Nothing throws.
The defense is a range assertion at every ingestion boundary, combined with a plausibility test against an expected extent. If a dataset is supposed to cover one country, every point should be inside a generous box around that country, and anything outside should be rejected rather than clipped.
Precision, accuracy, and the digits nobody earned
Decimal places in a coordinate imply a resolution. Each additional place divides the ground distance by ten. A handful of decimals gets to meter scale; a few more gets to centimeters and below, well past what any consumer positioning technology delivers.
Storing more digits than the source justifies is not harmful in itself, and it becomes harmful the moment those digits are read as accuracy. A consumer GPS fix carries an uncertainty measured in meters, more in dense urban settings where signals reflect off buildings. Writing that fix with ten decimal places does not improve it. It advertises a precision that is roughly seven orders of magnitude better than the measurement.
Two habits follow. Round to the precision the source supports, so the representation does not overstate the data. Carry an explicit accuracy value where one is available, because a coordinate without an uncertainty is a claim with no error bar, and downstream systems will treat it as exact.
The related trap is that repeated reprojection accumulates floating point drift. Converting between systems repeatedly, especially through low precision intermediate formats, moves coordinates by small amounts each time. Individually invisible, collectively enough to break exact topology: shared boundaries develop slivers, and features that used to snap together no longer do.
Null island and other tells
There is a point at zero latitude, zero longitude, in the Gulf of Guinea, where a surprising quantity of the world's data accumulates. Nothing is there. The coordinates are what a system produces when a parse failed and default numeric zeros were written, or when a geocoder returned nothing and the value was never checked.
A small set of similar signatures covers most coordinate corruption:
- Exactly zero for both values: a failed parse or an uninitialized record.
- A sign flip on one axis: a point mirrored into the wrong hemisphere, often landing in an ocean at the same distance from the equator or the prime meridian.
- Values off by a factor of ten or a hundred: a decimal separator lost during a locale sensitive parse, which is common when data crosses regions that use commas as the decimal mark.
- A tight cluster at the centroid of a country or a city: a geocoder fallback that resolved an unmatched address to the largest containing area, which manufactures a fake concentration of activity in the middle of nowhere in particular.
- Regular grid alignment in supposedly surveyed data: coordinates that have been snapped or rounded, often to the center of a cell.
Each of these is trivially detectable with a validation pass and almost impossible to spot in a table of numbers.
The rules that prevent nearly all of it
A short list, applied consistently, removes the large majority of coordinate defects.
- Never accept coordinates without a stated CRS, and never assume one. If the source does not declare it, treat the absence as a data quality defect and resolve it before ingestion, not after analysis.
- Store in a single geographic system, transform for measurement, transform back. One canonical internal representation removes an entire class of comparison errors.
- Use a real transformation library and let it apply datum shifts. Hand rolled formula conversions handle the projection and skip the datum, which is precisely the part that fails silently.
- Validate ranges and extents on ingestion. Latitude within the legal range, longitude within the legal range, and everything inside a generous bounding box for the expected coverage.
- Reject the known bad signatures explicitly, starting with exact zeros.
- Measure in a projection appropriate to the location and the property being measured, chosen deliberately, not inherited from whatever the file arrived in.
- Record accuracy alongside position, and round to what the source supports.
The failure that ships
The version that reaches production most often is a join that quietly loses a fraction of its matches. Two layers are overlaid, one in a national grid and one in a global geographic system, transformed with a projection change but no datum transformation. Everything lands within a couple of hundred meters of where it belongs. Most points still fall inside the correct polygon, because most polygons are much larger than the offset.
The ones that fail are the ones near boundaries, and boundaries are exactly where the interesting cases live: the parcels on the edge of a zone, the buildings at the margin of a flood extent, the assets just inside or just outside a jurisdiction. The error rate is small in aggregate and concentrated entirely in the population the analysis cares about most.
No exception is raised, the totals look reasonable, and the map looks right at any zoom that shows the whole study area. The only way to catch it is to check a known control point, at high zoom, against an independent reference, before trusting anything built on top of the layer. That check takes a few minutes. Skipping it has cost projects far more.