django/django · error · NotSupportedError

This backend does not support expressions for specifying dis

Error message

This backend does not support expressions for specifying distance in the dwithin lookup.

What it means

Raised as NotSupportedError by DWithinLookup.process_distance when the active database backend does not expose supports_dwithin_distance_expr and the supplied distance argument is an expression (has resolve_expression) that is not a Distance instance. SQLite/SpatiaLite and some older backends cannot compile an arbitrary expression into the third argument of ST_DWithin.

Source

Thrown at django/contrib/gis/db/models/lookups.py:345

                    self.lhs.output_field, self.rhs_params, self.lookup_name
                ),
            )
        )


@BaseSpatialField.register_lookup
class DWithinLookup(DistanceLookupBase):
    lookup_name = "dwithin"
    sql_template = "%(func)s(%(lhs)s, %(rhs)s, %(value)s)"

    def process_distance(self, compiler, connection):
        dist_param = self.rhs_params[0]
        if (
            not connection.features.supports_dwithin_distance_expr
            and hasattr(dist_param, "resolve_expression")
            and not isinstance(dist_param, Distance)
        ):
            raise NotSupportedError(
                "This backend does not support expressions for specifying "
                "distance in the dwithin lookup."
            )
        return super().process_distance(compiler, connection)

    def process_rhs(self, compiler, connection):
        dist_sql, dist_params = self.process_distance(compiler, connection)
        self.template_params["value"] = dist_sql
        rhs_sql, params = super().process_rhs(compiler, connection)
        return rhs_sql, (*params, *dist_params)


class DistanceLookupFromFunction(DistanceLookupBase):
    def as_sql(self, compiler, connection):
        spheroid = (
            len(self.rhs_params) == 2 and self.rhs_params[-1] == "spheroid"
        ) or None
        distance_expr = connection.ops.distance_expr_for_lookup(

View on GitHub (pinned to ae25a40be0)

Solutions

  1. Pass a concrete Distance(...) or numeric literal instead of an expression.
  2. If you need per-row distances, switch to a backend with supports_dwithin_distance_expr=True (PostGIS).
  3. Precompute the distance value in Python and pass it as D(m=value).

Example fix

// before
QS.filter(geom__dwithin=(pt, F('radius')))  # on SpatiaLite
// after
QS.filter(geom__dwithin=(pt, D(m=obj.radius)))
Defensive patterns

Strategy: fallback

Validate before calling

from django.db.models import Expression
from django.contrib.gis.measure import Distance
def coerce_dwithin_distance(backend_features, dist):
    if not backend_features.supports_dwithin_distance_expr and isinstance(dist, Expression) and not isinstance(dist, Distance):
        raise NotSupportedError('Resolve expression to a Distance before dwithin on this backend')
    return dist

Type guard

def is_dwithin_safe(backend_features, dist):
    return backend_features.supports_dwithin_distance_expr or isinstance(dist, Distance) or not hasattr(dist, 'resolve_expression')

Try / catch

from django.db import NotSupportedError
try:
    QS.filter(geom__dwithin=(pt, expr))
except NotSupportedError as e:
    if 'dwithin' in str(e):
        QS.filter(geom__dwithin=(pt, D(m=resolved_value)))

Prevention

When it happens

Trigger: On SpatiaLite, Model.objects.filter(geom__dwithin=(pt, F('radius'))) or an annotated expression. The features.supports_dwithin_distance_expr flag is False, dist_param is an Expression, and it is not a Distance, so lookups.py:345 raises.

Common situations: Developing locally on SQLite/SpatiaLite and deploying to PostGIS; passing an F() object or aggregate where a Distance measurement is expected.

Related errors


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