dgraph-io/dgraph · error

Expected a Geo type

Error message

Expected a Geo type

What it means

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.).

Source

Thrown at types/conversion.go:592

		case StringID, DefaultID:
			val, err := vc.MarshalText()
			if err != nil {
				return err
			}
			*res = string(val)
		case BinaryID:
			r, err := vc.MarshalBinary()
			if err != nil {
				return err
			}
			*res = r
		default:
			return cantConvert(fromID, toID)
		}
	case GeoID:
		vc, ok := val.(geom.T)
		if !ok {
			return errors.Errorf("Expected a Geo type")
		}
		switch toID {
		case BinaryID:
			r, err := wkb.Marshal(vc, binary.LittleEndian)
			if err != nil {
				return err
			}
			*res = r
		case StringID, DefaultID:
			val, err := geojson.Marshal(vc)
			if err != nil {
				return nil
			}
			*res = string(bytes.Replace(val, []byte("\""), []byte("'"), -1))
		default:
			return cantConvert(fromID, toID)
		}
	case PasswordID:

View on GitHub (pinned to 759e242be6)

Solutions

  1. Parse the textual geo value first with types.ParseValue into a Val whose Value is a geom.T, then Marshal it
  2. Ensure the Value is a concrete geom type, e.g. orb/geom.Point or geom.Polygon, when setting Tid: types.GeoID
  3. Check upstream code paths that construct geo Vals and add the missing parse/conversion step

Example fix

// before
types.Marshal(types.Val{Tid: types.GeoID, Value: `POINT(1 2)`}, out) // string, not geom.T
// after
var parsed types.Val
if err := types.ParseValue(types.GeoID, []byte(`POINT(1 2)`), &parsed); err == nil {
    err = types.Marshal(parsed, out)
}
Defensive patterns

Strategy: type-guard

Validate before calling

func isGeomVal(v types.Val) bool {
    _, ok := v.Value.(geom.T)
    return v.Tid == types.GeoID && ok
}
if isGeomVal(v) { types.Marshal(v, out) } else { /* parse via types.ParseValue first */ }

Type guard

func toGeoVal(raw string) (types.Val, error) {
    var out types.Val
    err := types.ParseValue(types.GeoID, []byte(raw), &out)
    return out, err // out.Value is guaranteed to be a geom.T on success
}

Prevention

When it happens

Trigger: 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.

Common situations: Building Val structs manually with GeoID but raw WKT text; passing GeoJSON strings without parsing; refactors that lost the types.ParseValue/parsing step.

Related errors


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