Find the geographic bug, not just the code bug.
GeoDebug:不让 Codex 在 GIS 上裸奔
Geospatial correctness checks for data and workflows.
Architecture · Rule catalog · Failure cases · Contributing · Security · Changelog · Releases
GeoMole · small offsets, big bugs.
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.
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 unknownThe code can be valid while the geography is not.
Install and see one failure immediately:
pip install geodebug
geodebug demoThen check a dataset or preflight an operation:
geodebug check roads.geojson
geodebug preflight roads.geojson --operation buffer --distance 500| 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 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.
Want the bugs, not the architecture?
Run five small failures that still produce valid-looking pipeline output. Read the field notes: 5 Geospatial Bugs That Valid Data and Passing Tests Won't Catch.
Each case builds its own local fixture, runs the bad workflow, and is exercised in CI.
source
│
▼
adapter ──► facts ──► rules ──► diagnostics ──► report
▲
│
dataset / relation / operation
Three questions drive the engine:
- Dataset — is this dataset internally spatially plausible?
- Relation — are these datasets compatible with each other?
- Operation — is this operation semantically valid for these coordinates and units?
Adapters observe. Rules diagnose. Policy decides what fails the build.
| Command | Purpose |
|---|---|
geodebug demo |
Run a built-in 500 m buffer failure |
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 --deepMachine-readable output is first-class:
geodebug check roads.geojson --format jsonpip install geodebug
geodebug demoNeed 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+.
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 GEO404Projects 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-01GeoDebug searches the current directory and its parents for .geodebug.toml. Use --config
to select one explicitly.
Profiles are intentionally simple:
default— rule defaultsstrict— warnings become errorsexploratory— warnings become notes
Explicit overrides win. Suppressions require a reason and may expire.
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.
UNKNOWNis notPASS. Missing evidence stays missing.- Policy does not rewrite truth. It changes severity or visibility, not the rule result.
- Expensive scans are explicit.
--deepmeans--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 configgit 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
pytestThe 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.
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.
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.
Geo to see. Geek to build.
GeoGeekLab