GeoJSON often fails in quiet, frustrating ways: the map loads, the layer code runs, and nothing appears. This guide is a practical debugging reference for developers who need to validate GeoJSON, isolate malformed geometry, and fix rendering issues without guessing. It covers a repeatable troubleshooting workflow, concrete examples of broken data, and the styling mistakes that make valid features appear invisible.
Overview
If your GeoJSON is not rendering, the problem is usually one of four things: the data is not valid JSON, the GeoJSON structure is wrong, the geometry is technically present but invalid for the renderer, or the map style makes the layer appear missing. The fastest way to debug is to stop treating it as one large problem and split it into small checks.
GeoJSON validation matters because mapping libraries are forgiving in different ways. One library may silently ignore a malformed feature. Another may drop only the invalid geometry. A third may throw a console warning that is easy to miss during normal development. That inconsistency is why a disciplined process works better than relying on trial and error.
At a high level, verify these items in order:
- Confirm the payload is valid JSON.
- Confirm the top-level object is valid GeoJSON such as
FeatureCollection,Feature, or a geometry object. - Check that every feature has the correct coordinate structure for its geometry type.
- Verify coordinate order and numeric ranges.
- Check whether the data falls inside the map viewport.
- Inspect layer styling, filters, and visibility settings.
- Test the same data in a minimal map example before blaming your application code.
This article focuses on the debugging side of mapping work. If the entire map is blank rather than just one dataset, see Why Your Map Is Blank: A Debugging Checklist for JavaScript Mapping Apps. If your app setup itself is unstable, Vite, React, and Map Libraries: Setup Guide with Common Build Fixes is a useful companion.
Core framework
Use this framework whenever you need an invalid GeoJSON fix or a quick path through geojson troubleshooting. The goal is to move from transport-level problems to geometry-level problems and finally to rendering-level problems.
1. Validate the JSON before you validate the GeoJSON
Many rendering failures start with plain JSON syntax errors: trailing commas, broken quoting, comments added by hand, or server responses that wrap the payload in unexpected text. Before checking anything map-specific, run the payload through a JSON parser or a trusted formatter. If the data cannot be parsed as JSON, no mapping library can help you.
Look for:
- Trailing commas in arrays or objects
- Single quotes instead of double quotes for keys and strings
- Comments inserted into JSON files
- Responses that contain HTML error pages instead of JSON
- Stringified GeoJSON nested inside another JSON field
A common failure case is receiving this from an API:
{
"data": "{"type":"FeatureCollection","features":[]}"
}The GeoJSON exists, but it is a string, not an object. You may need one extra JSON.parse() step.
2. Confirm the GeoJSON object type and shape
Once the payload parses, check whether its structure matches GeoJSON expectations. The top-level type field matters. If you pass a random object with a coordinates property, some libraries will simply ignore it.
Valid top-level patterns usually include:
{ "type": "FeatureCollection", "features": [...] }{ "type": "Feature", "geometry": {...}, "properties": {...} }{ "type": "Point", "coordinates": [...] }and other raw geometry objects
Check for these structural errors:
featureinstead ofFeaturefeatureCollectioninstead ofFeatureCollection- Missing
featuresarray on aFeatureCollection - Missing
geometryon aFeature propertiesset to an array instead of an object
Case sensitivity is easy to overlook. GeoJSON type names are not free-form labels.
3. Validate geometry by type
This is where most map data format errors show up. A valid Point does not use the same nesting depth as a Polygon, and a valid Polygon does not use the same nesting as a MultiPolygon.
Use this quick geometry checklist:
- Point:
[longitude, latitude] - LineString:
[[lng, lat], [lng, lat], ...] - Polygon:
[[[lng, lat], [lng, lat], ...]]where the first ring is the outer boundary - MultiPolygon:
[[[[lng, lat], ...]], [[[lng, lat], ...]]]
The most common errors here are wrong nesting depth, mixed geometry types inside one coordinate array, and accidental null values.
4. Check coordinate order and ranges
GeoJSON uses longitude first and latitude second. That single detail causes many cases of geojson not rendering, especially when coordinates come from forms, CSV files, or APIs that return latitude first.
Healthy coordinate range checks:
- Longitude should usually be between -180 and 180
- Latitude should usually be between -90 and 90
If you see [40.7128, -74.0060], that looks like New York in latitude-longitude order, but GeoJSON expects [-74.0060, 40.7128]. Swapped coordinates may place your features far from the expected region or produce no visible result if your map stays centered elsewhere.
5. Verify polygon rules and ring closure
Polygons are easy to break. A polygon ring should have at least four positions, and the first and last position in each ring should match to close the shape. Some tools repair this automatically. Others do not.
For example, this polygon is incomplete:
{
"type": "Polygon",
"coordinates": [
[[-73.99,40.75],[-73.98,40.75],[-73.98,40.76]]
]
}It needs a closing coordinate matching the first point, and in practice a valid ring should explicitly return to the starting position.
6. Separate data problems from style problems
Do not assume the data is broken just because nothing is visible. Valid GeoJSON can disappear under bad styling:
- Fill color matches the basemap
- Opacity is set to 0
- Stroke width is too thin to notice
- Layer filter excludes all features
- Zoom-based visibility hides the layer
- Z-order places the layer under a mask or opaque overlay
A strong debugging move is to temporarily apply loud default styles: bright red outlines, visible point radius, high opacity, and no filters.
7. Inspect the viewport and fit bounds
Sometimes the data is valid and styled correctly but simply not inside the current view. If you load GeoJSON from geocoding, user uploads, or mixed regional datasets, automatically fitting bounds is often the quickest proof that the renderer works.
If your library supports it, compute bounds from the dataset and zoom the map to those bounds. If the map flies somewhere unexpected, you have learned something useful: the coordinates are valid enough to render, but the location is not what you expected.
8. Reduce the problem to one feature
When a large dataset fails, isolate a single known feature and test it in a minimal example. If one point renders and the full file does not, the issue is likely in a later feature, a mixed geometry set, or a style/filter rule tied to specific properties. This approach saves time because you stop debugging the whole application and start debugging one object.
Practical examples
These examples cover common cases developers run into during geojson validation and day-to-day map debugging.
Example 1: Coordinates are swapped
Symptom: The layer loads with no errors, but features are missing from the expected city or country.
Broken:
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [40.7128, -74.0060]
},
"properties": {}
}Fixed:
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-74.0060, 40.7128]
},
"properties": {}
}Why it happens: Data sources and UI forms often use latitude, longitude order, while GeoJSON uses longitude, latitude.
Example 2: Wrong geometry nesting for Polygon
Symptom: Your polygon layer accepts the file but shows nothing, or the console reports invalid coordinates.
Broken:
{
"type": "Polygon",
"coordinates": [
[-73.99,40.75],[-73.98,40.75],[-73.98,40.76],[-73.99,40.75]
]
}Fixed:
{
"type": "Polygon",
"coordinates": [
[[-73.99,40.75],[-73.98,40.75],[-73.98,40.76],[-73.99,40.75]]
]
}Why it happens: Polygons require an array of rings, even if there is only one ring.
Example 3: FeatureCollection is structurally wrong
Symptom: The app fetches data successfully, but the source does not populate.
Broken:
{
"type": "FeatureCollection",
"feature": []
}Fixed:
{
"type": "FeatureCollection",
"features": []
}Why it happens: A small property naming mistake is enough to make the object invalid.
Example 4: Valid data, invisible style
Symptom: No geometry appears even though data inspection looks correct.
Check for:
fill-opacity: 0circle-radius: 0- A filter referencing a property that does not exist
- Line color matching the map background
Debug style: Temporarily use high-contrast defaults and remove all filters. If the data appears, the GeoJSON was fine and the style logic was the actual issue.
Example 5: One bad feature breaks confidence in the whole file
Symptom: A dataset with hundreds of features partially renders or renders inconsistently.
Approach: Split the collection into individual features, then test in batches. Invalid geometry often lives in one imported record with null coordinates, a malformed polygon ring, or a property type your style expression does not expect.
This is especially common in pipelines that merge CSV exports, geocoding results, and hand-edited spatial data.
Example 6: The response is not actually GeoJSON yet
Symptom: Your network tab shows successful data transfer, but rendering code receives an unexpected shape.
Typical cause: An API returns business objects like:
{
"locations": [
{ "lat": 40.7, "lng": -74.0, "name": "A" }
]
}Fix: Transform the response into GeoJSON before sending it to the map source:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-74.0, 40.7] },
"properties": { "name": "A" }
}
]
}That distinction matters. A mapping library expects GeoJSON, not just anything that contains coordinates.
Common mistakes
This section is a compact checklist of the issues that repeatedly cause geojson not rendering reports in real projects.
- Using latitude, longitude instead of longitude, latitude. This is probably the most frequent mistake.
- Passing string values instead of numbers. Some renderers coerce them, some do not, and some fail later during bounds or styling operations.
- Mixing geometry assumptions. Code written for points may quietly fail on polygons or multipolygons.
- Forgetting polygon closure. Unclosed rings and too-few positions are common import issues.
- Misreading silent failures. No visible error does not mean valid data.
- Applying filters to missing properties. If your style expects
statusbut your features usestate, the filter may exclude everything. - Trusting upstream exports without inspection. CSV-to-GeoJSON conversion tools can produce surprising field types, null coordinates, or malformed records.
- Skipping network inspection. A successful fetch status does not guarantee the response body contains the data shape you expect.
- Debugging inside a complex app too early. Move the data into a minimal map example first.
- Ignoring environment and fetch issues. Sometimes the data never arrives because of request configuration, CORS, or build-time variable mistakes rather than GeoJSON itself.
If your dataset is fetched from another service and never reaches the browser correctly, review CORS Errors with Mapping APIs: Common Causes and Fixes. If your problem sits in TypeScript definitions rather than geometry, TypeScript Types for Mapping Libraries: What Breaks and How to Fix It can help separate type-system noise from actual runtime issues.
A practical habit is to keep a small known-good GeoJSON fixture in your project. If that fixture renders and the live data does not, your renderer is probably fine. The bug is in the incoming payload, transformation step, or style logic. That single control sample makes troubleshooting much faster.
When to revisit
GeoJSON debugging is not something you learn once and forget. Revisit your validation process whenever the shape of your data pipeline changes.
Review this checklist when:
- You switch mapping libraries or rendering engines
- You start accepting uploaded spatial files from users
- You add a new conversion step from CSV, SQL results, or API responses
- You move from static datasets to live updates
- You introduce filters, expression-based styling, or clustering
- You begin mixing points, lines, and polygons in one workflow
For live systems, build GeoJSON checks into your normal development process rather than waiting for a visual failure. A durable workflow looks like this:
- Validate raw JSON at ingest.
- Normalize coordinates and field names during transformation.
- Reject or log malformed features instead of passing them through silently.
- Keep one small visual test dataset in the codebase.
- Use fit-bounds and high-contrast debug styles in development.
- Inspect the network response before you inspect map code.
- Test one feature in isolation whenever a full collection fails.
If your map stack grows more complex over time, this checklist remains useful because the underlying failure modes do not change much. The renderer may differ, the style syntax may differ, and the framework may differ, but malformed data, bad coordinate order, and invisible styles still cause most problems.
For teams working across API integrations, frontend tooling, and live map behavior, it also helps to document where GeoJSON is produced, where it is transformed, and where it is consumed. That makes future debugging less personal and more mechanical: you can identify whether the error was introduced upstream, during transformation, or at render time.
The practical takeaway is simple. When GeoJSON will not render, do not start by rewriting your map component. Start by validating the payload, checking geometry structure, confirming coordinate order, and stripping styles back to obvious defaults. That sequence resolves a large share of GeoJSON issues quickly, and it gives you a reusable process for the next dataset that breaks in a slightly different way.