{"record":{"id":"17f2744db2dccb21","repo":"dgraph-io/dgraph","slug":"got-empty-polygon","errorCode":null,"errorMessage":"Got empty polygon.","messagePattern":"Got empty polygon\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"types/s2.go","lineNumber":130,"sourceCode":"\n}\n\n// Intersects returns true if the two loops intersect.\nfunc Intersects(l1 *s2.Loop, l2 *s2.Loop) bool {\n\tif l2.NumEdges() > l1.NumEdges() {\n\t\t// Use the larger loop for edge indexing.\n\t\treturn intersects(l2, l1)\n\t}\n\treturn intersects(l1, l2)\n}\n\nfunc convertToGeom(str string) (geom.T, error) {\n\t// validate would ensure that we have a closed loop for all the polygons. We don't support open\n\t// loop polygons.\n\tclosed := func(p *geom.Polygon) error {\n\t\tcoords := p.Coords()\n\t\tif len(coords) == 0 {\n\t\t\treturn errors.Errorf(\"Got empty polygon.\")\n\t\t}\n\t\t// Check that first ring is closed.\n\t\tc := coords[0]\n\t\tl := len(c)\n\t\tif c[0][0] == c[l-1][0] && c[0][1] == c[l-1][1] {\n\t\t\treturn nil\n\t\t}\n\t\treturn errors.Errorf(\"Last coord not same as first\")\n\t}\n\n\tvalidate := func(g geom.T) (geom.T, error) {\n\t\tswitch v := g.(type) {\n\t\tcase *geom.MultiPolygon:\n\t\t\tfor i := range v.NumPolygons() {\n\t\t\t\tif err := closed(v.Polygon(i)); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/types/s2.go#L112-L148","documentation":"Thrown by the closed-loop validator inside convertToGeom (types/s2.go) when a GeoJSON Polygon has zero rings — an empty coordinates array. The library requires at least one closed ring to convert the polygon to S2 loops.","triggerScenarios":"Parsing a GeoJSON value like {\"type\":\"Polygon\",\"coordinates\":[]} or [[ ]] through convertToGeom (used by GetGeoTokens), so p.Coords() returns an empty slice.","commonSituations":"Malformed GeoJSON from client uploads, truncated JSON payloads, or empty polygon defaults written by other tools.","solutions":["Ensure the polygon has at least one ring in its coordinates before submitting","Validate GeoJSON with a schema/linter (e.g. geojsonhint) before sending","Reject empty coordinates at API ingress and return a 400 to the client"],"exampleFix":"// before\n{\"type\":\"Polygon\",\"coordinates\":[]}\n// after\n{\"type\":\"Polygon\",\"coordinates\":[[[0,0],[0,5],[5,5],[5,0],[0,0]]]}","handlingStrategy":"validation","validationCode":"var pl geojson.Polygon\njson.Unmarshal(raw, &pl)\nif len(pl.Coordinates) == 0 || len(pl.Coordinates[0]) == 0 {\n    return errors.New(\"polygon must contain at least one ring\")\n}","typeGuard":"func hasRings(p *geom.Polygon) bool {\n    return p != nil && len(p.Coords()) > 0\n}","tryCatchPattern":"g, err := types.ConvertToGeom(str)\nif err != nil && strings.Contains(err.Error(), \"Got empty polygon\") {\n    // return 400 invalid geometry to client\n}","preventionTips":["Validate GeoJSON structure before ingest","Reject empty coordinates arrays at API ingress","Fuzz/property-test geometry parsing with malformed inputs"],"tags":["geojson","polygon","validation"],"backgroundTag":"empty-polygon-geometry","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}