{"record":{"id":"9f0134bb16614521","repo":"dgraph-io/dgraph","slug":"expected-a-geo-type","errorCode":null,"errorMessage":"Expected a Geo type","messagePattern":"Expected a Geo type","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"types/conversion.go","lineNumber":592,"sourceCode":"\t\tcase StringID, DefaultID:\n\t\t\tval, err := vc.MarshalText()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t*res = string(val)\n\t\tcase BinaryID:\n\t\t\tr, err := vc.MarshalBinary()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t*res = r\n\t\tdefault:\n\t\t\treturn cantConvert(fromID, toID)\n\t\t}\n\tcase GeoID:\n\t\tvc, ok := val.(geom.T)\n\t\tif !ok {\n\t\t\treturn errors.Errorf(\"Expected a Geo type\")\n\t\t}\n\t\tswitch toID {\n\t\tcase BinaryID:\n\t\t\tr, err := wkb.Marshal(vc, binary.LittleEndian)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t*res = r\n\t\tcase StringID, DefaultID:\n\t\t\tval, err := geojson.Marshal(vc)\n\t\t\tif err != nil {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\t*res = string(bytes.Replace(val, []byte(\"\\\"\"), []byte(\"'\"), -1))\n\t\tdefault:\n\t\t\treturn cantConvert(fromID, toID)\n\t\t}\n\tcase PasswordID:","sourceCodeStart":574,"sourceCodeEnd":610,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/types/conversion.go#L574-L610","documentation":"types.Marshal raises this when the source Val claims Tid GeoID but its Value does not implement geom.T (the Go geom library geometry interface). Marshal type-asserts val.(geom.T) and this assertion failed, so the value is not actually a geometry object (point/polygon etc.).","triggerScenarios":"types.Marshal with from.Tid == GeoID and Value being a string, []byte, or other non-geom.T type — e.g. a WKT string placed directly in the Val instead of being parsed first.","commonSituations":"Building Val structs manually with GeoID but raw WKT text; passing GeoJSON strings without parsing; refactors that lost the types.ParseValue/parsing step.","solutions":["Parse the textual geo value first with types.ParseValue into a Val whose Value is a geom.T, then Marshal it","Ensure the Value is a concrete geom type, e.g. orb/geom.Point or geom.Polygon, when setting Tid: types.GeoID","Check upstream code paths that construct geo Vals and add the missing parse/conversion step"],"exampleFix":"// before\ntypes.Marshal(types.Val{Tid: types.GeoID, Value: `POINT(1 2)`}, out) // string, not geom.T\n// after\nvar parsed types.Val\nif err := types.ParseValue(types.GeoID, []byte(`POINT(1 2)`), &parsed); err == nil {\n    err = types.Marshal(parsed, out)\n}","handlingStrategy":"type-guard","validationCode":"func isGeomVal(v types.Val) bool {\n    _, ok := v.Value.(geom.T)\n    return v.Tid == types.GeoID && ok\n}\nif isGeomVal(v) { types.Marshal(v, out) } else { /* parse via types.ParseValue first */ }","typeGuard":"func toGeoVal(raw string) (types.Val, error) {\n    var out types.Val\n    err := types.ParseValue(types.GeoID, []byte(raw), &out)\n    return out, err // out.Value is guaranteed to be a geom.T on success\n}","tryCatchPattern":null,"preventionTips":["Never put raw WKT/GeoJSON strings in a Val with Tid GeoID","Always parse geo literals with types.ParseValue before marshaling","Keep geo values as geom.T types end to end"],"tags":["types","marshal","geo","type-assertion","api-misuse"],"backgroundTag":"geo-type-mismatch","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}