Short answer

A spatial dataset is not "done" when it draws correctly on your screen. It is done when another team can open it, place it in the right coordinate system, read the attributes without mojibake, and trust the geometry. This checklist covers the failure points that actually break handoffs: a missing or undefined CRS, invalid geometry, the wrong text encoding, format choices that don't survive the recipient's tools, and no metadata to explain any of it. Most "the data is corrupted" emails trace back to one of these five.

The format decision, made on the recipient's workflow

Choose the format from where the data is going, not from what you happen to have open.

  • GeoPackage (.gpkg) — an OGC standard built on SQLite. One file holds many vector layers, rasters, styles and attribute tables, with no field-name length limit and full UTF-8. This is the sane default for desktop and most database-adjacent exchange. It avoids every shapefile limitation below.
  • GeoJSON — per RFC 7946, coordinates are WGS84 longitude, latitude (EPSG:4326) and that ordering is mandatory. It is plain text, ideal for web maps and small datasets, but it bloats fast and has no spatial index, so it is the wrong choice for heavy analytical layers.
  • Shapefile (.shp) — still ubiquitous, but it is a set of files and carries hard limits: 10-character field names, a 2 GB per-file ceiling, one geometry type per file, and 8-bit encoding unless a .cpg declares otherwise. Deliver it only when the recipient explicitly needs it.
  • PostGIS — not a file format but a database. For database-to-database transfer use pg_dump of the spatial schema, or hand over a GeoPackage as an intermediary.

The shapefile trap, explained

The most frequent "broken data" report is an incomplete shapefile. The format spreads one logical layer across sidecar files:

  • .shp — geometry
  • .shx — geometry index
  • .dbf — attributes
  • .prj — CRS definition (WKT)
  • .cpg — character encoding declaration

Lose the .prj and the data has no CRS — it may draw in the ocean off West Africa (the null-island symptom of unprojected coordinates), or be silently assumed wrong by the recipient. Lose the .cpg and accented or non-Latin attribute text turns into garbage. Send only the .shp and there are no attributes or index at all. Always zip the complete file set, never the .shp alone.

Coordinate reference system discipline

The CRS is the single highest-impact field. Two checks:

  1. Is a CRS defined at all? An undefined CRS is worse than a wrong one because tools guess. In GeoPackage and PostGIS the SRID is stored with the geometry; in shapefile it lives only in the .prj.
  2. Is it the CRS the recipient expects? Web consumers usually want EPSG:4326 (or 3857 for tiles). Analysts working in metres want a projected CRS (a UTM zone, a national grid). If you reproject, do it deliberately with a real transformation, not a metadata relabel — ogr2ogr -t_srs EPSG:4326 out.gpkg in.gpkg actually moves coordinates, whereas assigning a SRID without transforming corrupts position.

State the CRS in the README in human terms ("EPSG:32631 — WGS84 / UTM zone 31N, units metres"), not just an opaque number.

Geometry and attribute validity

Invalid geometry — self-intersections, unclosed rings, duplicate vertices, ring-orientation errors — passes silently through display but breaks overlays, area calculations and database loads downstream. Check and fix before delivery:

  • QGIS: Check validity (Vector geometry), then Fix geometries.
  • PostGIS: SELECT id FROM layer WHERE NOT ST_IsValid(geom); then UPDATE layer SET geom = ST_MakeValid(geom);
  • GDAL: ogr2ogr -makevalid out.gpkg in.gpkg.

For attributes: confirm field names survive the target format (shapefile truncates to 10 chars and will silently rename population_density to populatio_1), confirm data types are preserved (dates and booleans are common casualties), and confirm encoding is UTF-8.

A worked validation pass with ogr2ogr / ogrinfo

Before sending a converted dataset, run:

ogrinfo -so -al delivery.gpkg

-so (summary only) reports per layer: geometry type, feature count, extent, and the CRS. Confirm the feature count matches the source (a conversion that dropped rows is a red flag), the extent sits where it should (an extent in the thousands when you expected millions of metres signals a CRS problem), and the CRS is what you intend.

Then convert with explicit control rather than menu-clicking:

ogr2ogr -f GPKG delivery.gpkg source.shp \
  -t_srs EPSG:4326 -makevalid -nlt PROMOTE_TO_MULTI -lco ENCODING=UTF-8

-nlt PROMOTE_TO_MULTI prevents the classic "mixed single/multi geometry" load failure, and -makevalid cleans geometry in the same pass.

The metadata record

Ship a short README or an embedded metadata table answering: source and provenance, acquisition/processing date, CRS (EPSG code and plain name), geometry type, attribute dictionary (field name, type, meaning, units), known limitations and allowed use. This is the difference between a dataset someone can reuse next year and one that becomes a mystery the moment you leave the project.

Common pitfalls and why they happen

  • Only the .shp is sent. It is the visible file; people forget the sidecars. Zip the set.
  • Missing .prj or null CRS. Data lands at null island or is assumed wrong. Verify with ogrinfo.
  • Encoding garbage. Non-UTF-8 dbf without a .cpg. Force ENCODING=UTF-8 on export.
  • Field-name truncation. Shapefile's 10-char limit renames fields silently. Use GeoPackage, or check the schema after conversion.
  • "It opened, so it's fine." Display tolerates invalid geometry that breaks analysis. Run a validity check.
  • Relabel instead of reproject. Setting a CRS without transforming moves nothing but the label, putting features in the wrong place.

QA and validation checklist

  • Format matches the recipient's workflow (GeoPackage default; GeoJSON only for web/small; shapefile only on request).
  • CRS defined, correct, and reprojected with a real transformation if needed.
  • Geometry validated and fixed; feature count matches source.
  • Encoding UTF-8; field names and types preserved.
  • Multi-layer deliveries packaged as one container (GeoPackage) or fully zipped.
  • README/metadata with source, date, CRS, schema and allowed use.
  • Final open in a clean session to confirm it draws in the right place.

Bathyl perspective

We treat delivery as a product step, not an export. Every dataset that leaves goes through the ogrinfo summary and a validity pass, and ships in a GeoPackage with an attribute dictionary, so the receiving team inherits something queryable and auditable rather than a puzzle.

Related reading

Sources