{"record":{"id":"79f6cf6cf194e775","repo":"dgraph-io/dgraph","slug":"require-a-polygon-for-intersects-query","errorCode":null,"errorMessage":"Require a polygon for intersects query","messagePattern":"Require a polygon for intersects query","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"types/geofilter.go","lineNumber":201,"sourceCode":"\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\n\tcase QueryTypeIntersects:\n\t\t// An intersects query is as the name suggests all the entities which intersect with the\n\t\t// given region. So we look at all the objects whose parents match our cover as well as\n\t\t// all the objects whose cover matches our parents.\n\t\tif len(loops) == 0 {\n\t\t\treturn nil, nil, errors.Errorf(\"Require a polygon for intersects query\")\n\t\t}\n\t\ttoks := parentCoverTokens(parents, cover)\n\t\treturn toks, &GeoQueryData{loops: loops, qtype: qt}, nil\n\n\tdefault:\n\t\treturn nil, nil, errors.Errorf(\"Unknown query type\")\n\t}\n}\n\n// MatchesFilter applies the query filter to a geo value\nfunc (q GeoQueryData) MatchesFilter(g geom.T) bool {\n\tswitch q.qtype {\n\tcase QueryTypeWithin:\n\t\treturn q.isWithin(g)\n\tcase QueryTypeContains:\n\t\treturn q.contains(g)\n\tcase QueryTypeIntersects:\n\t\treturn q.intersects(g)","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/types/geofilter.go#L183-L219","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n{\"type\":\"intersects\"} // no polygon\n// after\n{\"type\":\"intersects\",\"coordinates\":[[[0,0],[0,5],[5,5],[5,0],[0,0]]]}","handlingStrategy":"validation","validationCode":"if qt == QueryTypeIntersects && len(loops) == 0 {\n    return errors.New(\"intersects query requires a non-empty polygon\")\n}","typeGuard":"func hasLoops(loops []s2.Loop) bool { return len(loops) > 0 }","tryCatchPattern":"toks, data, err := types.GetGeoTokens(qt, pt, loops, cover, parents)\nif err != nil && strings.Contains(err.Error(), \"Require a polygon for intersects query\") {\n    // return a validation error to the caller\n}","preventionTips":["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"],"tags":["geo","query","validation"],"backgroundTag":"missing-geo-polygon","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}