Short answer
Shapefile attribute field names are capped at 10 characters because the attributes live in a 1980s-era dBASE (.dbf) table whose field-name slot in the header is a fixed 11-byte buffer — 10 usable ASCII characters plus a null terminator. When you export a layer whose fields are longer, the GIS silently truncates them, and if two long names share their first 10 characters they collide and get renumbered (area_per_1). The fix is to stop using shapefile for anything with rich attribution: GeoPackage, PostGIS, and GeoJSON have no such limit.
Where the limit comes from
A "shapefile" is not one file but a set: .shp (geometry), .shx (geometry index), .dbf (attributes), usually .prj (CRS), and sometimes .cpg (encoding). The attribute table is plain dBASE IV. In the dBF file structure, each field descriptor in the header reserves exactly 11 bytes for the field name, of which the last must be a null byte — leaving 10 characters for the name, ASCII only, conventionally uppercased.
This is not a GIS bug or an Esri choice that can be configured away; it is the binary layout of the container. No flag makes a shapefile hold an 11-character field name. That is why the limit is identical in QGIS, ArcGIS, GDAL/OGR, and everything else that writes the format.
What truncation actually does to your data
The danger is that truncation is silent and lossy. Consider a layer with these analysis fields:
sediment_thicknesssediment_typesample_depth_msample_date_utc
On export to shapefile, GDAL truncates to the first 10 characters:
sediment_thickness→sediment_tsediment_type→sediment_t← collisionsample_depth_m→sample_depsample_date_utc→sample_dat
The first two both become sediment_t, so the second is auto-renamed sediment_1. You now have sediment_t and sediment_1, and nothing in the file records which was thickness and which was type. A recipient opening the shapefile cannot recover the original meaning. Multiply this across a 40-column geochemistry table and the dataset becomes unusable without the original.
GDAL warns on the command line (Warning 6: Normalized/laundered field name: 'sediment_thickness' to 'sediment_t'), but those warnings scroll past in a batch job and are invisible when exporting through a GUI menu.
The other shapefile attribute limits
The 10-character name cap travels with a family of dBF constraints worth knowing before you commit data to the format:
- Text fields: 254 characters max. Longer strings are cut off. Free-text descriptions and notes overflow.
- No native date-time. dBF has a Date type but no time component; timestamps must be split or stored as text.
- No true boolean. Stored as a 1-character text field "T"/"F".
- NULL handling is weak. Many drivers cannot distinguish NULL from 0 or empty string.
- Numeric precision is fixed per field (width and decimals declared in the header); wide integers can overflow.
- ~255 fields maximum, and a practical 2 GB ceiling on each component file (
.shpand.dbf). - Encoding ambiguity. Without a
.cpgfile, non-ASCII characters (accents, diacritics) corrupt.
Why a 40-year-old limit still bites in 2026
The dBASE format predates GIS as we know it, yet shapefile remains everywhere because of inertia and interoperability: nearly every tool, portal, and legacy system can read it, so it became the lowest common denominator for data exchange. That ubiquity is precisely the trap. Data is born in a long-name-friendly environment (a PostGIS schema, a spreadsheet, a GeoPackage), gets exported to shapefile "because the client asked for it," and silently loses its attribute names at the boundary. The limit does not announce itself during analysis — it strikes at handoff, the moment when the person who understands the data and the person who receives it are different people.
The cost is highest in attribute-rich scientific data. A geochemistry table with assay columns like gold_ppb, arsenic_ppm, copper_pct, and iron_oxide_pct may survive, but the moment names grow descriptive — gold_detection_limit, gold_analysis_method — they collapse into gold_detec, gold_analy, or worse, collide. Borehole, geophysics, and sample datasets routinely carry dozens of such fields, and a single careless export can strip the dataset of the very metadata that makes it scientifically usable.
How to avoid the problem
Use a modern format. GeoPackage (.gpkg, an OGC SQLite-based standard) and PostGIS both allow long, descriptive, case-sensitive field names, true NULLs, datetime, 64-bit integers, and multiple layers in one container. GeoJSON (RFC 7946) has no field-name limit and is fine for small web-bound datasets, though it always uses WGS84 longitude/latitude.
Convert with ogr2ogr:
ogr2ogr -f GPKG samples.gpkg samples.shp
# shapefile -> geopackage; long names are preserved going the other way
ogr2ogr -f GPKG samples.gpkg samples_long.geojson
If you are forced to deliver shapefile, take control of truncation instead of letting it happen blind:
- Design 10-character names up front using a documented abbreviation scheme (
sed_thick,sed_type,samp_dep_m,samp_date). - Keep a field-alias / data dictionary mapping the short name to the full description, delivered alongside the file.
- Check for collisions before export — if two intended names share 10 characters, rename one.
- Verify the written schema:
ogrinfo -so samples.shp samples
Read back every field name and confirm none were renumbered.
Worked example: safe shapefile handoff
A client requires Esri shapefile for a legacy system. The working data is a GeoPackage with 22 descriptive columns.
- Build a mapping table:
full_name → 10_char_name(e.g.iron_oxide_pct → fe_ox_pct). - Rename in a copy with
ogr2ogr -sqlor QGIS field renaming, never on the master. - Export:
ogr2ogr -f "ESRI Shapefile" deliver.shp working.gpkg working_layer. - Run
ogrinfo -so deliver.shpand confirm all 22 names survived without_1suffixes. - Ship a
.cpg(UTF-8) plus the data dictionary so attribute meanings and accents are recoverable.
The master copy stays in GeoPackage; the shapefile is a disposable delivery artefact.
Common pitfalls and why they happen
- Exporting through a GUI and missing the warnings. The truncation message appears only in a log you did not open, so the loss is invisible until the recipient complains.
- Round-tripping through shapefile. Open a GeoPackage, export to shapefile, re-import: your long names are now permanently the truncated versions.
- Assuming a successful export means clean data. "It saved without an error" says nothing about whether two fields collided.
- Sending only the
.shp. Without.dbf/.shx/.prjthe dataset is incomplete — attributes and CRS are gone. - Relying on shapefile for datetime or NULLs. The format cannot represent them, so values are quietly altered.
Quality checks
- After any export to shapefile, run
ogrinfo -soand compare the field list against the source schema. - Search the new names for numeric suffixes (
_1,_2) that signal a collision. - Confirm a
.cpgaccompanies the file and matches the actual encoding (UTF-8). - Ship a data dictionary whenever names were abbreviated.
- For anything beyond a simple, small, ASCII dataset, prefer GeoPackage and document why if shapefile is unavoidable.
Bathyl perspective
We keep working data in GeoPackage or PostGIS where attribute names stay meaningful, and treat shapefile strictly as a constrained export target — never a master. When a client requires it, we design the 10-character schema deliberately and ship a data dictionary, so no column ever loses its meaning in transit.
Related reading
- Why Shapefile Encoding Breaks Accents
- When to Use GeoPackage Instead of Shapefile
- Why Your GIS Layers Do Not Line Up
- Spatial data products