Short answer

If a vector layer jumps to the wrong place after you reproject it, the transformation almost always started from a false premise: the software was told the data was in a CRS it was not actually in. Reprojection recomputes coordinates from a declared source CRS to a target CRS, so a wrong source declaration produces a precise, repeatable, and entirely wrong shift. The fix is to confirm the real source CRS first, keep "assign a CRS" and "reproject" as two separate operations in your head, and verify the output against a control point before trusting it.

Assigning a CRS is not the same as reprojecting

This is the single most common source of misplaced vector data, and it is worth being pedantic about because the two operations look similar in a menu but do opposite things to your coordinates.

Assigning (defining) a CRS changes only the metadata. The X/Y numbers stored in the geometry stay byte-for-byte identical; you are simply telling the software how to interpret them. In QGIS this is Layer Properties > Source > Assigned Coordinate Reference System, or in GDAL it is ogr2ogr -a_srs EPSG:2154 out.gpkg in.shp (note the lowercase a). You assign a CRS when the coordinates are already correct for that system but the .prj file is missing, corrupt, or wrong.

Reprojecting (transforming) recomputes every vertex. A point at longitude 2.35, latitude 48.85 in EPSG:4326 becomes roughly 651000, 6862000 in EPSG:2154 (RGF93 / Lambert-93). The numbers change because the coordinate system changed. In GDAL this is ogr2ogr -s_srs EPSG:4326 -t_srs EPSG:2154 out.gpkg in.shp, and in QGIS it is Vector > Data Management > Reproject Layer.

The classic failure: a shapefile is actually in Lambert-93 (planar metres, values like 651000) but its .prj says EPSG:4326. You "reproject to EPSG:2154", the software treats the metre values as degrees, and the layer lands somewhere near the equator off the coast of West Africa — the null island region — or simply vanishes off the visible extent. The cure was not a different reprojection; it was assigning the correct source CRS (EPSG:2154) and then leaving it alone or reprojecting onward.

Confirm the source CRS before you touch anything

Never trust the label blindly. Inspect both the declared CRS and the raw coordinate values, because the coordinates themselves tell you which CRS is plausible.

  • ogrinfo -al -so layer.shp reports the declared SRS plus the layer extent. If the SRS says EPSG:4326 but the extent reads 651000 6862000 : 660000 6871000, the declaration is lying — those are metres, not degrees.
  • Degrees fall in the range roughly -180 to 180 and -90 to 90. Anything larger is a projected system.
  • UTM eastings are typically 160000–834000; northings up to ~9300000. A "false easting" of 500000 is the giveaway for a UTM or Transverse Mercator zone.
  • For a shapefile, check that the .prj sidecar exists at all. A missing .prj means the layer has no declared CRS, which is a metadata problem to fix by assigning, not a transformation problem.

If you genuinely do not know the CRS, overlay the layer on a trusted reference (an OpenStreetMap basemap, a known administrative boundary) after trying a candidate CRS. The correct CRS is the one under which the features land on the right real-world locations.

The datum transformation step that gets skipped

A CRS bundles two things: a projection (how the curved earth is flattened) and a datum (the reference ellipsoid and its tie to the earth). Converting between two CRSs that share a datum is purely mathematical and lossless. Converting between different datums requires a datum transformation, and there is frequently more than one available with different accuracy and area of validity.

Examples that bite people:

  • NAD27 (EPSG:4267) to NAD83 (EPSG:4269) in North America. The shift varies by location and can exceed 100 m. A naive conversion that ignores the NADCON/HARN grid shift will be visibly off.
  • ED50 to ETRS89 in Europe — shifts on the order of tens to ~200 m depending on country.
  • WGS84 vs ETRS89 — these have drifted apart by roughly 0.5–0.8 m due to plate motion and are still often treated as identical, which is fine for mapping but not for survey-grade work.

In QGIS, when you reproject across datums the software offers a Datum Transformations dialog listing candidate operations with their accuracy and bounding area; pick the one whose area of use covers your project and whose accuracy meets your need. Behind the scenes this is PROJ choosing a pipeline. With GDAL you can let PROJ pick the best available operation, or pin it explicitly with -ct (coordinate transformation pipeline) or by installing the relevant PROJ grid shift files so the high-accuracy transform is even available. If the grids are absent, PROJ silently falls back to a lower-accuracy null or three-parameter shift — a quiet source of metre-level error.

A worked workflow

Say you receive a contractor's shapefile of borehole collars, you need it in your project CRS (RGF93 / Lambert-93, EPSG:2154), and you must buffer each collar by 50 m.

  1. Inspect: ogrinfo -al -so collars.shp. It reports EPSG:4326 and an extent in the range of decimal degrees (2.3 / 48.8). Good — the declaration is consistent with the values.
  2. Reproject with an explicit datum-aware transform:
    ogr2ogr -s_srs EPSG:4326 -t_srs EPSG:2154 \
            -f GPKG collars_l93.gpkg collars.shp
    
    RGF93 and WGS84 are aligned to within centimetres, so the datum step here is negligible — but you should still know that, not assume it.
  3. Buffer in a projected CRS: now that coordinates are in metres, a 50 m buffer is meaningful. In PostGIS the equivalent is ST_Buffer(geom, 50) on a geometry stored as SRID 2154. Buffering in EPSG:4326 with a radius of "50" would mean 50 degrees, which is nonsense.
  4. Verify: pick one borehole whose real position you know (a surveyed monument, a corner you can see on imagery) and confirm the reprojected coordinate matches within tolerance. Measure a known distance and confirm it reads in metres at the right magnitude.

Common pitfalls and why they happen

  • Buffering or measuring in a geographic CRS. Degrees are angular, not linear, so distances and areas computed from latitude/longitude are wrong and vary with latitude. Reproject to a suitable projected CRS (a local UTM zone, a national grid) first. This happens because the map displays fine via on-the-fly reprojection, hiding the underlying unit mismatch.
  • Trusting on-the-fly reprojection for analysis. QGIS happily renders mismatched layers together. Display alignment does not mean the stored coordinates are analysis-ready.
  • Using Web Mercator (EPSG:3857) for measurement. It is a display projection for tiled basemaps; its scale distortion grows enormously toward the poles. Use it to show data on a slippy map, never to compute distance or area.
  • Missing PROJ grid files. The transform "works" but uses a degraded fallback, putting data systematically off by a constant offset. This is invisible unless you check against control.
  • Re-reprojecting an already-correct layer because it "looked wrong", compounding error. Diagnose first.

QA and validation

Before the layer enters a deliverable, confirm: the source, processing, and output CRS are all recorded; at least one feature matches a trusted control point within tolerance; a known distance measures correctly in linear units; the layer overlays a reference dataset cleanly at the edges of the extent, not just the centre; and the datum transformation used (and its accuracy) is documented if datums were crossed. For a vector dataset, ST_IsValid or QGIS Check Geometries afterwards catches any vertices mangled by an extreme transformation.

Bathyl perspective

We treat the source-CRS confirmation as a gate, not a formality: nothing gets reprojected until its real CRS is verified against the coordinate values themselves. Recording the source, transformation pipeline, and accuracy alongside the output means a later analyst can audit the spatial chain instead of re-deriving it from a layer that simply "looks about right".

Related reading

Sources