Skip to content
Latchkey

How to Install GDAL in CI Without Version-Mismatch Failures

GDAL is one of the hardest Python packages to install in CI: the Python binding must exactly match the system GDAL C library version, or the build fails.

The GDAL Python package binds to the system GDAL C/C++ library, and the binding version must match the installed libgdal version exactly. CI runners rarely have GDAL at all, and even when they do, a version skew between libgdal-dev and the pip package breaks the build. The reliable path is to install the system library first and pin the binding to its version.

Why it fails in CI

The GDAL Python binding builds against the system GDAL headers and calls gdal-config to discover the version. With no system GDAL installed, gdal-config is missing; with a mismatched version, the build compiles against the wrong API and fails. Pip alone cannot fix this - the C library has to be there first.

  • gdal-config not found / Could not find gdal-config during the build.
  • Version mismatch: pip install gdal==X where X differs from the installed libgdal.
  • fatal error: gdal.h: No such file or directory - no GDAL dev headers.

Install it reliably

Install libgdal-dev (the system library and headers) first, read its version from gdal-config, then install the matching Python binding version. Pinning the binding to the system GDAL version is the key step.

Terminal
# 1) System GDAL + headers
apt-get update && apt-get install -y libgdal-dev gdal-bin build-essential
# 2) Read the system version and pin the binding to it
export GDAL_VERSION=$(gdal-config --version)
pip install "GDAL==${GDAL_VERSION}.*"

Cache & speed

Installing libgdal-dev pulls many geospatial dependencies and is slow - bake GDAL into a custom runner image (or use an official GDAL Docker image) instead of apt on every job. Cache ~/.cache/pip for the binding.

.github/workflows/ci.yml
- uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: pip-gdal-${{ hashFiles('requirements*.txt') }}

Common errors

ErrorCauseFix
gdal-config not foundNo system GDALapt-get install libgdal-dev
gdal.h: No such file or directoryNo GDAL dev headersapt-get install libgdal-dev
Version mismatch on buildBinding != libgdal versionPin GDAL==$(gdal-config --version)
Slow apt every jobReinstalling GDAL each runBake into image / use GDAL container

Key takeaways

  • Install libgdal-dev first; the binding cannot build without it.
  • Pin the Python GDAL binding to gdal-config --version exactly.
  • Bake GDAL into the image or use a GDAL container - apt is slow.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →