dgraph-io/dgraph · error

Require a polygon for within query

Error message

Require a polygon for within query

What it means

This error is thrown by queryTokensGeo in types/geofilter.go when a 'within' geo query is issued without any polygon loops. A within query requires a polygon to compute the cell cover that is prefixed with parentPrefix to build index tokens; without loops there is nothing to cover.

Source

Thrown at types/geofilter.go:177

	if qt == QueryTypeNear {
		if len(loops) == 0 {
			return nil, nil, errors.Errorf("Internal error while processing near query.")
		}
		cover = coverLoop(loops[0], MinCellLevel, MaxCellLevel, MaxCells)
		parents = getParentCells(cover, MinCellLevel)
	} else {
		parents, cover, err = indexCells(g)
		if err != nil {
			return nil, nil, err
		}
	}

	switch qt {
	case QueryTypeWithin:
		// For a within query we only need to look at the objects whose parents match our cover.
		// So we take our cover and prefix with the parentPrefix to look in the index.
		if len(loops) == 0 {
			return nil, nil, errors.Errorf("Require a polygon for within query")
		}
		toks := createTokens(cover, parentPrefix)
		return toks, &GeoQueryData{loops: loops, qtype: qt}, nil

	case QueryTypeContains:
		// 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

View on GitHub (pinned to 759e242be6)

Solutions

  1. Include a valid polygon (GeoJSON Polygon with closed ring) in the within query before calling GetGeoTokens
  2. Validate that loops/polygon is non-empty before constructing a QueryTypeWithin query
  3. If you only have a point, switch the query type to QueryTypeNear or QueryTypeContains as appropriate

Example fix

// before
toks, data, err := queryTokensGeo(dgraph.QueryTypeWithin, pt, nil, cover, parents)
// after
loops := convertPolygonToLoops(polygon) // ensure polygon provided
toks, data, err := queryTokensGeo(dgraph.QueryTypeWithin, pt, loops, cover, parents)
Defensive patterns

Strategy: validation

Validate before calling

if len(loops) == 0 || polygon == nil {
    return errors.New("within query requires a non-empty polygon")
}

Type guard

func hasPolygon(p geom.T) bool {
    poly, ok := p.(*geom.Polygon)
    return ok && poly != nil && len(poly.Coords()) > 0
}

Try / catch

toks, data, err := types.GetGeoTokens(qt, pt, loops, cover, parents)
if err != nil && strings.Contains(err.Error(), "Require a polygon for within query") {
    // reject/repair the query: return 400 to client
}

Prevention

When it happens

Trigger: Calling GetGeoTokens (or queryTokens) with QueryTypeWithin but no polygon in the query payload, e.g. an empty or missing GeoJSON polygon in the within filter.

Common situations: Users building geo queries programmatically forget to attach the polygon, or pass a query object where the polygon field is nil/omitted due to JSON deserialization dropping the coordinates key.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/3dbb606177cca924. Report an issue: GitHub.