The fastest way to find the problem

When layers in a GIS project misbehave, the cause is almost always one of four things: a layer whose declared CRS does not match the coordinates stored in it, a missing or wrong datum transformation, planar measurements taken in a geographic (degree-based) CRS, or a vertical datum mismatch in elevation data. A CRS audit is the disciplined process of testing each of these in order, using the metadata that the software actually reads rather than what you assume is true.

The single most useful habit is to separate two questions that beginners conflate: what CRS does the file claim to be in? and what CRS are the coordinates actually in? When those two disagree, every downstream operation is silently wrong even though nothing errors out.

What a CRS actually encodes

A coordinate reference system is a triple: a datum (a model of the Earth's shape and its tie to physical reference stations), a coordinate system (axis order, units, and origin), and — for projected systems — a map projection that flattens the ellipsoid onto a plane. Two CRSs can share a datum but differ in projection (for example EPSG:4326 and EPSG:32631 both use WGS 84), and two can share a projection family but differ in datum (NAD83 vs WGS 84 UTM zones look identical until you measure the offset).

The practical consequences:

  • EPSG:4326 (WGS 84 geographic) stores longitude/latitude in decimal degrees. A degree of longitude is about 111 km at the equator but shrinks toward the poles, so any planar buffer or area computed directly in 4326 is wrong.
  • Projected CRSs such as UTM zones (EPSG:326xx north, 327xx south) or national grids store eastings/northings in metres, suitable for distance and area.
  • Datum differences between NAD83 and WGS 84 reach roughly 1–2 m in North America; between older datums like ED50 and WGS 84 they can exceed 100 m. These differences are invisible on a basemap but fatal for cadastral or engineering work.

Step 1 — Read the declared CRS with the right tools

Do not trust the layer name or a colleague's note. Read the metadata the engine reads.

For a vector file:

ogrinfo -al -so survey_points.shp
gdalsrsinfo -o epsg survey_points.prj

For a raster:

gdalinfo dem_block.tif | grep -A2 "Coordinate System"

In PostGIS:

SELECT ST_SRID(geom), Find_SRID('public', 'parcels', 'geom')
FROM parcels LIMIT 1;

Note that a shapefile's .prj is a WKT string with no EPSG code — GDAL infers the code, and the inference can fail for slightly non-standard WKT, leaving the layer as "unknown CRS." That alone explains a large share of "my layer disappeared" reports.

Step 2 — Test whether the declaration is true

Pick one feature whose real-world location you know (a road junction, a survey monument, a building corner). Read its raw coordinates:

ogrinfo -al survey_points.shp | grep -A1 "POINT"

Now sanity-check the magnitude against the declared CRS:

  • Values like 2.351, 48.857 are degrees — the file is geographic, regardless of what the .prj claims.
  • Values like 448000, 5411000 are UTM-scale eastings/northings in metres.
  • Values in the hundreds of thousands that do not fit any UTM zone for the region often indicate a national grid (for example British National Grid EPSG:27700, or Lambert-93 EPSG:2154 for France).

If the numbers are degrees but the layer is declared as a metre-based projected CRS, you have a wrong declaration, not a reprojection problem. Fix it by assigning the correct source CRS, never by reprojecting.

Step 3 — Distinguish "assign" from "reproject"

This is the decision that resolves most alignment failures:

  • Assign / define CRS changes the label only. The coordinate numbers are untouched. Use it when the data has no CRS or the wrong CRS label but the numbers are genuinely already in the intended system. QGIS: Layer ▸ Set CRS or the "Assign projection" Processing algorithm. GDAL: gdal_edit.py -a_srs EPSG:2154 file.tif or ogr2ogr -a_srs.
  • Reproject / warp recomputes the coordinates from a known source CRS into a target CRS. Use it when the numbers are correct for their current system and you need them in another. QGIS: "Reproject layer". GDAL: ogr2ogr -t_srs EPSG:32631 out.gpkg in.gpkg or gdalwarp -t_srs EPSG:32631 in.tif out.tif.

Assigning a CRS to "make a layer move" is the classic anti-pattern: it appears to fix the display while corrupting the geometry's meaning.

Step 4 — Audit the datum transformation

When source and target sit on different datums, PROJ must apply a transformation, ideally with a grid-shift file (for example NTv2 grids, or the NADCON/HARN grids in North America). Inspect what PROJ intends to do before you trust it:

projinfo -s EPSG:4267 -t EPSG:4326 -o PROJ

If the only operation is a "null transformation" or a 3-parameter Helmert when a 7-parameter or grid-based one exists, expect an offset. In QGIS, Settings ▸ Options ▸ Transformations lets you pin the preferred operation; check that the chosen pipeline has an accuracy figure appropriate for your work (sub-metre for engineering, a few metres for regional mapping).

Step 5 — Audit measurement and vertical units

Two separate traps:

  1. Planar measurements in a geographic CRS. A buffer of "1000" in EPSG:4326 is 1000 degrees, which is nonsense. Reproject to an equidistant or UTM CRS first, or use a geodesic measurement tool (QGIS measure tool with ellipsoidal measurement enabled, or PostGIS geography type with ST_Distance).
  2. Vertical units in elevation data. A DEM in feet processed with a slope algorithm expecting metres yields slopes inflated by 3.28x. Confirm vertical units in the raster metadata, and remember the horizontal CRS says nothing about the vertical datum (EGM2008 geoid heights vs ellipsoidal heights vs a local tidal datum can differ by tens of metres).

A worked diagnosis

Symptom: a parcels layer (declared EPSG:2154, Lambert-93) sits ~400 km north-east of the aerial imagery (EPSG:3857).

  1. ogrinfo -al -so parcels.shp confirms the declaration is Lambert-93.
  2. Reading one geometry shows coordinates like 652000, 6862000 — plausible Lambert-93 metres. So the declaration is correct; this is not an assign problem.
  3. The imagery is fine. The misalignment magnitude (hundreds of km) is far too large for a datum offset, so it is a reprojection issue at display time — QGIS project CRS was set to EPSG:2154 and the imagery had no CRS, so it was being interpreted as Lambert-93 metres. Assigning EPSG:3857 to the imagery resolves it.

The lesson: the size of the offset is itself a diagnostic. Metres to tens of metres points to datum issues; hundreds of km points to wrong CRS labels or mixed degree/metre interpretation.

QA checklist before you trust the project

  • Every layer has an explicit, verified CRS (declaration matches coordinate magnitude).
  • The project CRS is a projected system appropriate to the extent, not Web Mercator, if any measurement will occur.
  • Datum transformations are pinned and their accuracy is acceptable for the deliverable.
  • One control point reprojects to its known true coordinates within tolerance.
  • Vertical units and vertical datum of any elevation layer are recorded.

Bathyl perspective

We treat the CRS audit as the first hour of any project we inherit, before producing a single derivative. The audit output is a short table — per layer: declared CRS, verified CRS, transformation used, units — that travels with the deliverable so the chain can be re-checked by anyone later.

Related reading

Sources