dgraph-io/dgraph · error
Require a polygon for intersects query
Error message
Require a polygon for intersects query
What it means
Thrown by queryTokensGeo when an intersects query is issued without polygon loops. Intersects queries build tokens from both parents and cover of the provided polygon; with no loops, neither side of the index scan can be constructed.
Source
Thrown at types/geofilter.go:201
// For a contains query, we only need to look at the objects whose cover matches our
// parents. So we take our parents and prefix with the coverPrefix to look in the index.
return createTokens(parents, coverPrefix), &GeoQueryData{pt: pt, loops: loops, qtype: qt}, nil
case QueryTypeNear:
if pt == nil {
return []string{}, nil, errors.Errorf("Require a point for a within query.")
}
// A near query is the same as the intersects query. We form a loop with the given point and
// the radius and then see what all does it intersect with.
toks := parentCoverTokens(parents, cover)
return toks, &GeoQueryData{loops: loops, qtype: QueryTypeIntersects}, nil
case QueryTypeIntersects:
// An intersects query is as the name suggests all the entities which intersect with the
// given region. So we look at all the objects whose parents match our cover as well as
// all the objects whose cover matches our parents.
if len(loops) == 0 {
return nil, nil, errors.Errorf("Require a polygon for intersects query")
}
toks := parentCoverTokens(parents, cover)
return toks, &GeoQueryData{loops: loops, qtype: qt}, nil
default:
return nil, nil, errors.Errorf("Unknown query type")
}
}
// MatchesFilter applies the query filter to a geo value
func (q GeoQueryData) MatchesFilter(g geom.T) bool {
switch q.qtype {
case QueryTypeWithin:
return q.isWithin(g)
case QueryTypeContains:
return q.contains(g)
case QueryTypeIntersects:
return q.intersects(g)View on GitHub (pinned to 759e242be6)
Solutions
- Provide a valid GeoJSON polygon (closed ring) for the intersects query
- Validate that the polygon parses into non-empty loops before issuing the query
- If intersecting with a point, use QueryTypeNear instead
Example fix
// before
{"type":"intersects"} // no polygon
// after
{"type":"intersects","coordinates":[[[0,0],[0,5],[5,5],[5,0],[0,0]]]} Defensive patterns
Strategy: validation
Validate before calling
if qt == QueryTypeIntersects && len(loops) == 0 {
return errors.New("intersects query requires a non-empty polygon")
} Type guard
func hasLoops(loops []s2.Loop) bool { return len(loops) > 0 } Try / catch
toks, data, err := types.GetGeoTokens(qt, pt, loops, cover, parents)
if err != nil && strings.Contains(err.Error(), "Require a polygon for intersects query") {
// return a validation error to the caller
} Prevention
- Validate the intersects filter schema (must be Polygon/MultiPolygon) before tokenization
- Reject point/linestring geometries for intersects upstream
- Log the original GeoJSON when polygon parsing yields zero loops
When it happens
Trigger: Calling GetGeoTokens/queryTokens with QueryTypeIntersects and an empty/missing polygon (len(loops) == 0), e.g. an intersects filter whose GeoJSON polygon failed to parse or was omitted.
Common situations: GeoJSON polygon stripped by a serializer, a user passing a point or linestring where a polygon is required, or an earlier decode error silently producing zero loops.
Related errors
- Require a polygon for within query
- Require a point for a within query.
- Invalid compare function %q
- expand() not allowed inside shortest
- Node with count cannot have child attributes
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/79f6cf6cf194e775.
Report an issue: GitHub.