GIS format conversions do not crash loudly when they fail. They produce an output file, report success, and leave you with data that is wrong in ways you may not notice until the analysis is already done. Field names get silently cut at 10 characters. Geometries disappear without warning. Coordinate systems shift without errors. Attribute types coerce to something that looks right but produces wrong numbers.

These are not edge cases. They are the default behavior of the tools most GIS teams use daily — including GDAL/OGR, QGIS’s built-in export, and ArcGIS Pro’s geoprocessing toolbox. None warn you by default.

1. Shapefile Field Name Truncation

The DBF format underlying shapefiles enforces a 10-character field name limit. This is a 40-year-old constraint from dBASE III, and it hits every team converting from modern formats where field names are descriptive.

When you convert a GeoJSON or GeoPackage with fields like building_type_code, last_inspection_date, and construction_material to a shapefile, these become building_ty, last_inspe, and constructio. The truncation is silent. No warning. No error. The conversion reports success. The output has 10-character field names.

If downstream SQL queries, Python scripts, or QGIS expressions reference the original field name, they fail at query time — not at conversion time, where the problem would be obvious.

The failure compound: when two fields truncate to the same 10 characters — municipality_name and municipality_note both become municipali — one silently overwrites the other. You now have two fields with the same name and only the last-written value survives.

What to check: After any GeoJSON-to-shapefile conversion, compare the field names in the output .dbf against your input schema. The GeoJSON-to-shapefile field truncation problem affects every tool that writes DBF. A quick ogrinfo -al -so output.shp | grep "^ " lists all field names and types in the DBF — run it and compare against your input schema before distributing the file.

The structural fix: Either rename fields before conversion (keep names under 10 characters in snake_case), or stay in GeoPackage or FlatGeobuf as the working format for projects where field names are semantically important. Only convert to shapefile at the final delivery step, with a documented field rename map.

2. CRS Mismatch and Silent Coordinate Shift

GeoJSON is supposed to use EPSG:4326 (WGS 84 geographic, decimal degrees) per RFC 7946. Shapefiles store CRS information in a .prj file — which is optional. Many shapefile consumers read the .prj when present, ignore it when absent, and assume EPSG:4326 when missing.

The failure mode: you export a layer from QGIS that is in a projected CRS (EPSG:32633, UTM Zone 33N) and save it as GeoJSON without reprojecting first. The GeoJSON file contains meter coordinates — values like (400000, 5500000) — but RFC 7946 conformance means any reader treats these as decimal degrees. A coordinate of 400,000° east, 5,500,000° north does not exist on Earth. Features land in the wrong location on every map that opens the file.

No error occurs because the file is syntactically valid GeoJSON. It has coordinates. The coordinates are wrong. Nothing complains until someone puts the file on a basemap and wonders why the features are in the ocean.

This also runs the other direction: a shapefile correctly in EPSG:4326 gets opened in a project set to EPSG:3857 (Web Mercator), and if on-the-fly reprojection is disabled, the features appear offset from their correct position by a value proportional to the latitude. At equatorial latitudes, the offset is zero. At 50° north (northern Europe, most of Canada), it is several kilometers.

What to check: Always verify the CRS of the output layer against the intended reference system. In QGIS: right-click layer > Layer Properties > Source. With GDAL: ogrinfo -al -so <file> prints the SRS block at the top. If the SRS reads GEOGCS["WGS 84"...] and you expected a projected CRS — or vice versa — something went wrong upstream. Do not distribute the file until this matches.

For automated pipelines: include an explicit -t_srs EPSG:4326 in any ogr2ogr call that produces GeoJSON for web delivery, and an explicit -t_srs EPSG:<your_project_crs> for any output that goes into a local projected dataset. Never rely on implicit CRS inheritance from the input.

3. Mixed Geometry Type Stripping

GeoJSON FeatureCollections can contain Points, LineStrings, Polygons, and GeometryCollections mixed in the same file. GeoPackage supports this. Shapefiles do not: each shapefile holds exactly one geometry type.

When GDAL converts a mixed-geometry GeoJSON to shapefile without explicit type filtering, it writes only the first geometry type it encounters and silently drops all features with different geometry types. The output file count does not match the input. No error. No summary of what was dropped.

The exact behavior varies by GDAL version and options:

  • Without type options: writes first-encountered geometry type, drops the rest
  • With -nlt PROMOTE_TO_MULTI: promotes single geometries (Point → MultiPoint) but still drops geometry-type mismatches
  • With explicit -where "OGR_GEOMETRY = 'POLYGON'": filters to the target type and produces a correct single-type shapefile

What to check: Count features in the input and output. ogrinfo -al -so input.geojson gives the feature count for each layer. If the shapefile has fewer features, geometry type mismatch is the first thing to investigate.

For inputs with mixed types, split by geometry type before converting:

ogr2ogr -where "OGR_GEOMETRY = 'POINT'" output_points.shp input.geojson
ogr2ogr -where "OGR_GEOMETRY = 'POLYGON'" output_polygons.shp input.geojson

This produces separate shapefiles per type — each complete, each correctly attributed — rather than one file that silently dropped two-thirds of your features.

GeoConvert validates geometry types before conversion and reports the split when a mixed input is detected, rather than silently producing a subset.

4. Null and Invalid Geometry Dropping

Features with null geometry (null in GeoJSON, empty WKT in PostGIS) are valid in most modern formats. Shapefiles have no null geometry concept — a feature either has geometry or it does not exist in the file. When GDAL encounters a null-geometry feature during conversion:

  • Default behavior: skip the feature entirely and continue. No warning unless verbose logging (-progress or --debug) is enabled.
  • With -skipfailures: continue past failures including null geometry, no report of what was skipped.

Invalid geometry is a separate but related issue: self-intersecting polygons, zero-area rings, and coordinate repetition in line strings are structurally valid in the file format but cause geometry operations to fail or produce wrong results downstream. GDAL does not validate geometry by default during conversion — it writes what it receives.

A self-intersecting polygon passes through ogr2ogr without error and writes to the shapefile. When you later run a spatial join, buffer, or intersection analysis on that feature, the result is either incorrect or produces a GEOS error that the tool reports cryptically as “TopologyException” — with no reference to the specific feature that caused it.

What to check:

  • Null geometry: compare feature count before and after. ogrinfo -al -so input.geojson | grep "Feature Count" vs ogrinfo -al -so output.shp | grep "Feature Count".
  • Invalid geometry: in QGIS, use Vector > Geometry Tools > Check Geometry Validity before any conversion that will go into analysis. In PostGIS: SELECT ST_IsValid(geom), ST_IsValidReason(geom) FROM layer WHERE NOT ST_IsValid(geom).

For batch validation of shapefiles before ingest, the shapefile validation preflight checklist covers the specific QGIS and GDAL commands for CRS, field length, geometry validity, and encoding checks.

5. Attribute Type Coercion

GeoJSON attribute types are dynamic: a numeric field might contain integers in most features but a string value ("N/A" or null) in one feature, and the format permits this. GDAL infers field types by scanning the first N features (default 100). If the first 100 features all have integer values in a field, GDAL declares the field as Integer. When it reaches the feature with "N/A", it either coerces the value — which produces 0 for a failed integer parse — or writes null.

Shapefile DBF supports only four attribute types: Character (string), Number (fixed-precision numeric), Date (YYYYMMDD), and Logical (boolean). GeoJSON’s richer type system maps onto this with losses:

GeoJSON typeDBF resultWhat can go wrong
booleanLogical (T/F)Works correctly
integerNumber (0 decimals)Works, but large integers (>9 digits) may overflow DBF width
floatNumber (fixed decimal places)Precision limited by DBF column width; trailing digits truncated
stringCharacter (max 254 chars)Strings longer than 254 characters are silently truncated
object / array (nested JSON)Character (JSON serialized) or droppedBehavior is driver-dependent; always verify nested properties survived

The last row is where real data loss occurs. If your GeoJSON has features with nested properties — a properties.address that is itself an object with street, city, postcode — the converter must either serialize the whole object as a string (which works if the string fits in 254 characters) or drop it. Which one it does depends on the GDAL version, the field width, and whether -lco RESIZE=YES was used.

What to check: After conversion involving text attributes, check that:

  • Numeric fields with long values haven’t been truncated by DBF width limits (a DBF Number field has a total width including the decimal point, set at field creation based on the widest value in the scan window)
  • String fields that contained long values are not truncated at 254 characters
  • Nested JSON properties either arrived as string representations or are explicitly handled before conversion

A useful sanity check for any conversion: open the DBF file in QGIS, select a representative feature, and compare its attribute values field-by-field against the corresponding feature in the source. Any truncation or type coercion is visible here before the data ships.

The broader reason many of these problems occur is that GeoJSON is being used as a working format instead of an interchange format. As a working format it is too permissive — mixed types, nested objects, and mixed geometry types that work in GeoJSON cause problems in every downstream format. Our GeoJSON interchange vs working format guide explains why GIS teams that process at scale use GeoPackage or PostGIS as the working layer and produce GeoJSON only at the delivery step.

The Practical Checklist

Before trusting any GIS format conversion output:

  1. Count features: input count == output count (or document why not)
  2. Check field names: no unexpected 10-char truncation vs your input schema
  3. Verify CRS: output CRS matches the intended reference system
  4. Validate geometry: no invalid geometry, no unexpected null geometry drop
  5. Spot-check attribute values: verify numeric precision and string length in at least 3–5 representative features, including edge cases (long strings, null values, large numbers)

The shapefile validation preflight checklist has the specific QGIS and GDAL commands for each of these checks. The free and open source GIS tools comparison covers how different conversion tools handle these edge cases — some are more conservative about type inference, some warn on mixed geometry types. The right tool depends on whether your priority is speed, correctness, or explicitness about what was dropped.