Short answer
Before a QGIS map or dataset leaves your machine, run a fixed pre-flight pass: verify the CRS of every layer against the project CRS, repair invalid geometry, confirm attribute schema and NoData handling, audit labels and rendering at the publication scale, and export with the correct resolution and georeferencing. The goal is that someone who reopens the project — or imports your output into PostGIS or ArcGIS Pro — gets the same numbers and the same picture you saw.
A checklist matters in QGIS specifically because the application is forgiving at display time and strict at analysis time. On-the-fly reprojection hides CRS mismatches, temporary scratch layers vanish on close, and a layout that looks sharp on screen can export as a blurry 96 dpi raster. The checks below catch the failures that only surface downstream.
1. Coordinate reference systems
CRS errors are the most expensive class of bug because they are invisible until someone measures something. QGIS reprojects layers on the fly to the project CRS, so a layer stored in EPSG:4326 (WGS 84, degrees) will visually align over a project set to EPSG:3857 or a national grid — but any length or area you compute in degrees is meaningless.
Checks:
- Open the status bar bottom-right and confirm the project CRS. For terrain and engineering work this should be a projected CRS in metres (a UTM zone such as EPSG:32630, or a national system like EPSG:2154 RGF93 Lambert-93, EPSG:27700 OSGB36 British National Grid).
- For each layer, open Layer Properties > Source and compare its declared CRS. A layer whose declared CRS is wrong (common with shapefiles that lost their
.prj) will land in the ocean or be silently reprojected from the wrong datum. - Never use Set CRS to "fix" a misplaced layer unless you are correcting a mislabel. If coordinates need to physically move, reproject:
Vector > Data Management Tools > Reproject Layer(algorithmnative:reprojectlayer) or, from the shell,ogr2ogr -t_srs EPSG:2154 out.gpkg in.shp. - For area and length fields, use ellipsoidal measurement (Project Properties > General > Measurements) or compute in a projected CRS.
$areain the field calculator respects the project ellipsoid setting;area($geometry)returns planar units of the layer CRS.
2. Geometry and topology validity
Invalid geometry breaks dissolves, intersections, and exports to strict formats, and it produces wrong areas. Run validity before any overlay.
- Vector > Geometry Tools > Check Validity (algorithm
qgis:checkvalidity). Choose the GEOS method; it flags self-intersections, nested shells, and incorrect ring orientation. It outputsvalid_output,invalid_output, anderror_outputlayers — inspect the error layer's point geometries to find exactly where the problem is. - Repair with Fix Geometries (
native:fixgeometries), which applies a zero-width buffer / make-valid pass. Re-run Check Validity afterward; "fixed" multipolygons sometimes collapse slivers you did not intend to lose. - For shared boundaries, use the Topology Checker plugin with rules such as must not have gaps, must not overlap, and must not have dangles. This catches the cartographically invisible 0.001 m gaps between adjacent polygons that ruin a coverage.
- Check for duplicate vertices and null geometries (
native:deleteduplicategeometries, and filtergeometry_is_empty($geometry)in the expression selector).
3. Attribute integrity
The geometry can be perfect while the table is wrong.
- Confirm field types. A numeric code stored as text will sort 1, 10, 2 and break joins. Shapefiles silently truncate field names to 10 characters and reals to limited precision — if you see truncated names, you exported to the wrong format; prefer GeoPackage.
- Scan for NULLs and empty strings in fields that drive symbology or labels. Use Select by Expression:
"depth_m" IS NULL OR "depth_m" = ''. - Validate ranges and domains with expressions, e.g.
"slope_pct" < 0 OR "slope_pct" > 100. Out-of-range values usually mean a unit or a derivation error upstream. - Check that join and relation keys are unique and present before exporting; a one-to-many join left in place will duplicate rows on export.
4. Rasters, NoData and rendering
- Confirm the NoData value is set and honoured (Layer Properties > Transparency). A DEM with NoData stored as
0instead of-9999will pull hillshades and slope to sea level around the edges. - Check the resampling for display vs analysis. Bilinear/cubic is fine for visualisation; analysis should run on native pixels.
- For styled rasters, lock the min/max stretch to fixed values rather than "min/max of current extent", or the colour ramp will shift as the user pans.
5. Cartography and labels at publication scale
- Set the canvas to the exact output scale (e.g. 1:25 000) before judging labels. Labels placed at 1:5 000 will collide at 1:25 000.
- Verify scale-dependent visibility so dense layers drop out when zoomed away.
- Confirm fonts are installed; missing fonts substitute silently and shift layout. Embed or package fonts on handoff.
6. Project hygiene
- Replace temporary (scratch) layers — the ones with the memory icon — with saved GeoPackage layers. They are gone on close.
- Use relative paths (Project Properties > General > Save paths: Relative) so the project survives moving folders.
- Save important results as named outputs and keep the Processing History (Processing > History) so a derivation can be replayed.
Worked example: pre-flight a slope map for a report
- Status bar shows project CRS EPSG:32630. The DEM reads EPSG:4326 in Layer Properties. Reproject:
gdalwarp -t_srs EPSG:32630 -r bilinear -tr 10 10 srtm.tif dem_utm.tif. - Generate slope:
gdaldem slope dem_utm.tif slope.tif -p(-pgives percent; omit for degrees — state which in the legend). - Check the DEM NoData:
gdalinfo dem_utm.tif | grep NoData. If absent, set it:gdalwarp -dstnodata -9999 .... - Style the slope layer with a fixed-value singleband pseudocolor ramp (0, 5, 15, 30, 60 %), not min/max-of-extent.
- In the Layout, set Export resolution = 300 dpi, tick Always export as vectors for the legend text, and for a GeoTIFF output enable World file.
- Export, then reopen the GeoTIFF in a fresh project to confirm it lands in the right place and the legend matches the data.
Common pitfalls and why they happen
- Right place, wrong numbers. On-the-fly reprojection makes a degrees layer look correct over a metres project, so area/length come out in degrees. Fix by forcing a projected CRS for any measurement.
- "Fixed" geometry that lost features. Fix Geometries can drop sub-pixel slivers and collapse degenerate rings. Always diff feature counts before and after.
- Blurry print export. The layout defaulted to screen resolution; nobody changed Export resolution to 300 dpi. Vector text exported as raster compounds it.
- Edge artefacts in terrain products. DEM NoData was 0, so hillshade and slope treated voids as flat ground at elevation zero.
- Broken project on a colleague's machine. Absolute paths plus scratch layers. Relative paths and saved outputs prevent it.
QA / validation
A fast end-of-job pass: reopen the saved project from a different folder; confirm every layer loads and reports its intended CRS; run qgis:checkvalidity once more on edited layers; reload the exported GeoTIFF/PDF in a clean project and visually overlay it on a known basemap. If all four pass, the deliverable is reproducible.
Bathyl perspective
We treat the checklist as a gate, not a habit: a map or dataset is not "done" until CRS, validity, attributes, and export have each been signed off and the project reopens cleanly from scratch. The payoff is that any teammate can reproduce a slope class or a contour line from the saved project without reverse-engineering the analyst's session.
Related reading
- QGIS Data Source Management
- QGIS Workflow for Consultant Reports
- QGIS vs ArcGIS for Geological and Terrain Workflows
- GIS and spatial analysis