{"record":{"id":"3dbb606177cca924","repo":"dgraph-io/dgraph","slug":"require-a-polygon-for-within-query","errorCode":null,"errorMessage":"Require a polygon for within query","messagePattern":"Require a polygon for within query","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"types/geofilter.go","lineNumber":177,"sourceCode":"\tif qt == QueryTypeNear {\n\t\tif len(loops) == 0 {\n\t\t\treturn nil, nil, errors.Errorf(\"Internal error while processing near query.\")\n\t\t}\n\t\tcover = coverLoop(loops[0], MinCellLevel, MaxCellLevel, MaxCells)\n\t\tparents = getParentCells(cover, MinCellLevel)\n\t} else {\n\t\tparents, cover, err = indexCells(g)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t}\n\n\tswitch qt {\n\tcase QueryTypeWithin:\n\t\t// For a within query we only need to look at the objects whose parents match our cover.\n\t\t// So we take our cover and prefix with the parentPrefix to look in the index.\n\t\tif len(loops) == 0 {\n\t\t\treturn nil, nil, errors.Errorf(\"Require a polygon for within query\")\n\t\t}\n\t\ttoks := createTokens(cover, parentPrefix)\n\t\treturn toks, &GeoQueryData{loops: loops, qtype: qt}, nil\n\n\tcase QueryTypeContains:\n\t\t// For a contains query, we only need to look at the objects whose cover matches our\n\t\t// parents. So we take our parents and prefix with the coverPrefix to look in the index.\n\t\treturn createTokens(parents, coverPrefix), &GeoQueryData{pt: pt, loops: loops, qtype: qt}, nil\n\n\tcase QueryTypeNear:\n\t\tif pt == nil {\n\t\t\treturn []string{}, nil, errors.Errorf(\"Require a point for a within query.\")\n\t\t}\n\t\t// A near query is the same as the intersects query. We form a loop with the given point and\n\t\t// the radius and then see what all does it intersect with.\n\t\ttoks := parentCoverTokens(parents, cover)\n\t\treturn toks, &GeoQueryData{loops: loops, qtype: QueryTypeIntersects}, nil\n","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/types/geofilter.go#L159-L195","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Include a valid polygon (GeoJSON Polygon with closed ring) in the within query before calling GetGeoTokens","Validate that loops/polygon is non-empty before constructing a QueryTypeWithin query","If you only have a point, switch the query type to QueryTypeNear or QueryTypeContains as appropriate"],"exampleFix":"// before\ntoks, data, err := queryTokensGeo(dgraph.QueryTypeWithin, pt, nil, cover, parents)\n// after\nloops := convertPolygonToLoops(polygon) // ensure polygon provided\ntoks, data, err := queryTokensGeo(dgraph.QueryTypeWithin, pt, loops, cover, parents)","handlingStrategy":"validation","validationCode":"if len(loops) == 0 || polygon == nil {\n    return errors.New(\"within query requires a non-empty polygon\")\n}","typeGuard":"func hasPolygon(p geom.T) bool {\n    poly, ok := p.(*geom.Polygon)\n    return ok && poly != nil && len(poly.Coords()) > 0\n}","tryCatchPattern":"toks, data, err := types.GetGeoTokens(qt, pt, loops, cover, parents)\nif err != nil && strings.Contains(err.Error(), \"Require a polygon for within query\") {\n    // reject/repair the query: return 400 to client\n}","preventionTips":["Always attach a polygon to within queries at the query-builder layer","Unit-test each query type with complete payloads","Validate GeoJSON filters at API ingress"],"tags":["geo","query","validation"],"backgroundTag":"missing-geo-polygon","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}