Skip to main content

GeoDebug

Find the geographic bug, not just the code bug.

Geospatial correctness checks for data and workflows.

CI Release License: MIT Python Typed

Architecture · Rule catalog · Contributing · Security · Changelog · Releases


Your file opens. Your geometry is valid. Your tests pass.

Your result can still be geographically wrong.

✓ file readable
✓ geometry valid
✓ pipeline completed
✓ tests passed
? geographically correct

GeoDebug checks the last question. It catches spatial-semantic failures that ordinary software tests and file validators can miss: CRS misuse, impossible coordinates, raster-grid misalignment, cross-dataset incompatibility, NoData/mask conflicts, and operations whose units do not mean what the code assumes.

See the gap

This workflow can run without raising a Python exception:

roads = gpd.read_file("roads.geojson")
buffered = roads.buffer(500)
buffered.to_file("roads_buffer.geojson")

But if the data uses a geographic CRS, 500 is interpreted in angular coordinate units rather than meters.

GeoDebug makes that failure explicit before the operation becomes a result:

$ geodebug preflight roads.geojson --operation buffer --distance 500

roads.geojson
ERROR GEO501  Buffer distance is interpreted in angular coordinate units.
  crs.kind: geographic
  crs.axis_units: degree, degree
  operation.distance: 500
1 error(s) · 0 warning(s) · 0 note(s) · 1 unknown

The code can be valid while the geography is not.

Install:

pip install geodebug

Then check a dataset or preflight an operation:

geodebug check roads.geojson
geodebug preflight roads.geojson --operation buffer --distance 500

Where GeoDebug fits

Layer Question
Parser / schema Can the data be read and interpreted structurally?
Geometry validity Is the geometry structurally valid?
Software tests Does the program behave as specified?
GeoDebug Does the data or operation make geographic sense?

GeoDebug does not replace GDAL, GeoPandas, Shapely, Rasterio, or PyProj. It turns spatial facts exposed by the geospatial stack into a systematic, deterministic geospatial correctness layer with stable diagnostics that can run locally or in CI.

No LLM in the core. No silent CRS guessing. No automatic "fix everything."

GeoDebug architecture, diagnostic scopes, rule families, and CLI example

What it catches

GeoDebug is built for bugs that ordinary syntax checks and file validators often miss.

Domain Examples
CRS missing CRS, impossible angular coordinates, data outside a projected CRS area of use
Vector invalid geometry
Raster singular affine transforms, NoData/mask conflicts
Relations non-overlapping datasets, half-pixel raster grid shifts
Operations metric buffer, planar area, or planar distance on a geographic CRS

A file can be valid in isolation and still be wrong for the operation you are about to run. That distinction is the point.

Mental model

source
  │
  ▼
adapter ──► facts ──► rules ──► diagnostics ──► report
                        ▲
                        │
              dataset / relation / operation

Three questions drive the engine:

  1. Dataset — is this dataset internally spatially plausible?
  2. Relation — are these datasets compatible with each other?
  3. Operation — is this operation semantically valid for these coordinates and units?

Adapters observe. Rules diagnose. Policy decides what fails the build.

CLI

Command Purpose
geodebug inspect DATA Show normalized spatial facts without diagnosing
geodebug check DATA Run dataset diagnostics
geodebug compare A B Run dataset + relational diagnostics
geodebug preflight DATA --operation ... Check operation semantics before execution
geodebug rules list Inspect the built-in rule corpus
geodebug schema Print the canonical report schema

Full geometry or raster scans are opt-in:

geodebug check landcover.tif --deep

Machine-readable output is first-class:

geodebug check roads.geojson --format json

Install

pip install geodebug

Need every adapter:

pip install "geodebug[all]"

Optional extras keep the core small:

Extra Support
core GeoJSON
vector GeoPackage, Shapefile, FlatGeobuf
raster GeoTIFF, COG, VRT
parquet GeoParquet
geopandas in-memory GeoDataFrame
all all optional adapters

Requires Python 3.12+.

Diagnostic corpus

GeoDebug ships 11 built-in rules with stable IDs.

Family Rules
CRS GEO101 missing CRS · GEO103 coordinate range · GEO105 area of use
Vector GEO201 invalid geometry
Raster GEO301 affine transform · GEO304 NoData/mask conflict
Relations GEO402 spatial overlap · GEO404 grid alignment
Operations GEO501 buffer · GEO502 area · GEO503 distance/length

Every released rule has an explicit contract for PASS, FAIL, UNKNOWN, and NOT_APPLICABLE.

geodebug rules show GEO404

Project policy

Projects can tune severity, disable rules, and suppress known exceptions without changing rule truth values.

schema_version = "1"
profile = "default"
fail_on = "error"

[rules]
disable = []

[rules.severity]
GEO101 = "error"

[[suppress]]
rule = "GEO103"
path = "legacy/*.geojson"
reason = "Known upstream coordinate convention"
expires = 2027-01-01

GeoDebug searches the current directory and its parents for .geodebug.toml. Use --config to select one explicitly.

Profiles are intentionally simple:

  • default — rule defaults
  • strict — warnings become errors
  • exploratory — warnings become notes

Explicit overrides win. Suppressions require a reason and may expire.

Contracts over vibes

A few things GeoDebug refuses to blur:

  • Adapters do not diagnose. They normalize observations into facts.
  • Rules do not perform I/O. They evaluate spatial invariants.
  • UNKNOWN is not PASS. Missing evidence stays missing.
  • Policy does not rewrite truth. It changes severity or visibility, not the rule result.
  • Expensive scans are explicit. --deep means --deep.
  • Automatic repair is conservative. A geometrically valid output is not necessarily a scientifically valid fix.

The canonical report schema is versioned independently at 1.0.0; project config uses schema version 1.

geodebug schema
geodebug schema --kind config

Development

git clone https://github.com/GeoGeekLab/geodebug.git
cd geodebug

python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev,all]'

ruff check .
mypy src/geodebug
pytest

The release gate checks more than unit tests: four-state rule contracts, golden must_not_report cases, metamorphic corrections, clean-corpus silence, cross-platform smoke tests, and installation from a freshly built wheel.

See Architecture, Diagnostic rules, and Releasing for the internals.

Contributing

Contributions should start from a concrete geospatial failure mode or a concrete engineering improvement. New diagnostics must preserve the four-state rule contract and include false-positive coverage where adjacent rules can cascade.

See CONTRIBUTING.md.

Security

Please report vulnerabilities privately through GitHub's security reporting features when available. Do not publish exploit details in a public issue before a fix or mitigation is available.

See SECURITY.md.

License

MIT


Geo to see. Geek to build.

GeoGeekLab

Release files for geodebug 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for geodebug 0.1.1
File Size Uploaded
geodebug-0.1.1.tar.gz 47.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for geodebug 0.1.1
File Interpreter ABI Platform
geodebug-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 97.7 kB

Release files / geodebug-0.1.1.tar.gz

Download URL geodebug-0.1.1.tar.gz
Size 47.0 kB
Tags Source
SHA-256 checksum
How to use checksums
45cd0e338b6bdd520ba028686b9743d2332e51afdafa9a8a17481884d1fb277a
BLAKE2b-256 checksum
How to use checksums
684e5041897167cdf67b85bbb34184e598292493bbaf74acf5f8328ffc212e4d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release files / geodebug-0.1.1-py3-none-any.whl

Download URL geodebug-0.1.1-py3-none-any.whl
Size 50.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4ae2e66cb15143d7129b336546e2d8760ab0f84b5b205ae3f174d7c52c2e5b2b
BLAKE2b-256 checksum
How to use checksums
cb38f6c29920ca60bc53e6ab67566b3fbf22c4ab0fe8e5694ae2c1572802e4e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.2

2 release files

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page