django/django · error · TypeError

Cannot set %s SpatialProxy (%s) with value of type: %s

Error message

Cannot set %s SpatialProxy (%s) with value of type: %s

What it means

Raised as TypeError by SpatialProxy.__set__ (the descriptor for GeometryField/RasterField) when assigning a value whose type does not match any accepted form. For raster fields only None/str/dict/raster instances are accepted; for geometry fields None/str/memoryview/GEOSGeometry instances are accepted; everything else is rejected at proxy.py:82.

Source

Thrown at django/contrib/gis/db/models/proxy.py:82

        gtype = self.field.geom_type

        if gtype == "RASTER" and (
            value is None or isinstance(value, (str, dict, self._klass))
        ):
            # For raster fields, ensure input is None or a string, dict, or
            # raster instance.
            pass
        elif isinstance(value, self._klass):
            # The geometry type must match that of the field -- unless the
            # general GeometryField is used.
            if value.srid is None:
                # Assigning the field SRID if the geometry has no SRID.
                value.srid = self.field.srid
        elif value is None or isinstance(value, (str, memoryview)):
            # Set geometries with None, WKT, HEX, or WKB
            pass
        else:
            raise TypeError(
                "Cannot set %s SpatialProxy (%s) with value of type: %s"
                % (instance.__class__.__name__, gtype, type(value))
            )

        # Setting the object's dictionary with the value, and returning.
        instance.__dict__[self.field.attname] = value
        return value

View on GitHub (pinned to ae25a40be0)

Solutions

  1. Convert the value: GEOSGeometry(wkt_or_hexewkb) for geometries, memoryview(wkb) for raw WKB, or GDALRaster(dict) for rasters.
  2. Pass None to clear the field.
  3. For shapely or geojson-py objects, serialize to WKT/GeoJSON first and wrap in GEOSGeometry.

Example fix

// before
obj.geom = shapely_geom
// after
from django.contrib.gis.geos import GEOSGeometry
obj.geom = GEOSGeometry(shapely_geom.wkt)
Defensive patterns

Strategy: type-guard

Validate before calling

from django.contrib.gis.geos import GEOSGeometry
from django.contrib.gis.gdal import GDALRaster
def coerce_geom_value(field, value):
    if field.geom_type == 'RASTER':
        if value is None or isinstance(value, (str, dict, GDALRaster)):
            return value
    elif value is None or isinstance(value, (str, memoryview, GEOSGeometry)):
        return value
    raise TypeError(f'Unsupported value type for {field.attname}: {type(value)}')

Type guard

def is_assignable_to_field(field, value):
    if field.geom_type == 'RASTER':
        return value is None or isinstance(value, (str, dict, GDALRaster))
    return value is None or isinstance(value, (str, memoryview, GEOSGeometry))

Try / catch

try:
    obj.geom = incoming
except TypeError as e:
    if 'SpatialProxy' in str(e):
        obj.geom = GEOSGeometry(incoming.wkt) if hasattr(incoming, 'wkt') else None

Prevention

When it happens

Trigger: instance.geom = 12345, instance.geom = ['POINT(0 0)'], or instance.raster = b'\x89PNG...' (bytes) for a raster field. The descriptor checks isinstance against the field class and the whitelisted scalar types.

Common situations: Assigning raw WKB bytes (should be memoryview), a list/dict for a geometry field (raster-only), an int ID, or a shape from another library (shapely) that is not a GEOSGeometry.

Related errors


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