django/django · error · GEOSException

Calling transform() with no SRID set is not supported.

Error message

Calling transform() with no SRID set is not supported.

What it means

Raised by GEOSGeometry.transform (geometry.py:496-520) as a GEOSException when the geometry has no SRID (srid is None) or a negative SRID and the caller passed a target SRID/transform that is not already a gdal.CoordTransform. Reprojection requires a known source SRS, so Django refuses to guess.

Source

Thrown at django/contrib/gis/geos/geometry.py:518

        PROJ string. By default, transform the geometry in-place and return
        nothing. However if the `clone` keyword is set, don't modify the
        geometry and return a transformed clone instead.
        """
        srid = self.srid

        if ct == srid:
            # short-circuit where source & dest SRIDs match
            if clone:
                return self.clone()
            else:
                return

        if isinstance(ct, gdal.CoordTransform):
            # We don't care about SRID because CoordTransform presupposes
            # source SRS.
            srid = None
        elif srid is None or srid < 0:
            raise GEOSException(
                "Calling transform() with no SRID set is not supported."
            )

        # Creating an OGR Geometry, which is then transformed.
        g = gdal.OGRGeometry(self._ogr_ptr(), srid)
        g.transform(ct)
        # Getting a new GEOS pointer
        ptr = g._geos_ptr()
        if clone:
            # User wants a cloned transformed geometry returned.
            return GEOSGeometry(ptr, srid=g.srid)
        if ptr:
            # Reassigning pointer, and performing post-initialization setup
            # again due to the reassignment.
            capi.destroy_geom(self.ptr)
            self.ptr = ptr
            self._post_init()
            self.srid = g.srid

View on GitHub (pinned to ae25a40be0)

Solutions

  1. Set an explicit SRID before transforming: geom.srid = 4326; geom.transform(3857).
  2. Construct the geometry with the SRID up front: GEOSGeometry('POINT(0 0)', srid=4326).
  3. If only the target SRS is known, build a gdal.CoordTransform(source_srs, dest_srs) and pass that instead of a bare SRID.

Example fix

// before
geom.transform(3857)  # geom.srid is None
// after
geom.srid = 4326
geom.transform(3857)
Defensive patterns

Strategy: validation

Validate before calling

def safe_transform(geom, target):
    if geom.srid is None or geom.srid < 0:
        geom.srid = 4326  # or raise, depending on policy
    return geom.transform(target)

Type guard

def geometry_has_srid(geom):
    return geom.srid is not None and geom.srid >= 0

Try / catch

from django.contrib.gis.geos.error import GEOSException
try:
    geom.transform(3857)
except GEOSException:
    geom.srid = 4326  # assume WGS84
    geom.transform(3857)

Prevention

When it happens

Trigger: Calling geom.transform(3857) (or any int/WKT/PROJ-string target) on a geometry whose geom.srid is None or < 0 and where the target is not a CoordTransform (a CoordTransform bundles its own source SRS and bypasses this check).

Common situations: Loading geometries from WKT without specifying an SRID, geometries deserialized from formats that drop SRID, or input pipelines that forget to call geom.srid = 4326. Also from negative SRIDs used as 'unknown' sentinels.

Related errors


AI-assisted analysis of django/django@ae25a40be0 (2026-08-06). Data as JSON: /api/errors/f8980eea64aeef45. Report an issue: GitHub.