cayleygraph/cayley · error

unsupported type: %v

Error message

unsupported type: %v

What it means

writeAsQuads converts Go values into quads and only handles strings, numerics, bools, and structs. If, after unwrapping, the reflect kind is not Struct (maps are also unsupported per the TODO), it cannot serialize the value and returns this error naming the type.

Source

Thrown at schema/writer.go:155

	// check if it's a type that quads package supports
	// note, that it may be a struct such as time.Time
	if val, ok := quad.AsValue(rv.Interface()); ok {
		return val, nil
	} else if kind == reflect.String {
		return quad.String(rv.String()), nil
	} else if kind == reflect.Int || kind == reflect.Uint ||
		kind == reflect.Int32 || kind == reflect.Uint32 ||
		kind == reflect.Int16 || kind == reflect.Uint16 ||
		kind == reflect.Int8 || kind == reflect.Uint8 {
		return quad.Int(rv.Int()), nil
	} else if kind == reflect.Float64 || kind == reflect.Float32 {
		return quad.Float(rv.Float()), nil
	} else if kind == reflect.Bool {
		return quad.Bool(rv.Bool()), nil
	}
	// TODO(dennwc): support maps
	if kind != reflect.Struct {
		return nil, fmt.Errorf("unsupported type: %v", rt)
	}
	// get conversion rules for this struct type
	rules, err := w.c.rulesFor(rt)
	if err != nil {
		return nil, fmt.Errorf("can't load rules: %v", err)
	}
	if len(rules) == 0 {
		return nil, fmt.Errorf("no rules for struct: %v", rt)
	}
	// get an ID from the struct value
	id, err := w.c.idFor(rules, rt, rv, "")
	if err != nil {
		return nil, err
	}
	if id == nil {
		id = w.c.genID(prv.Interface())
	}
	// save a node ID to avoid loops

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Convert the value to a supported type (string, number, bool, or struct) before writing
  2. Serialize maps to JSON strings before writing
  3. Model nested data as structs with schema tags instead of maps

Example fix

// before
w.WriteAsQuads(qs, val) // val is map[string]interface{}
// after
b, _ := json.Marshal(val)
w.WriteAsQuads(qs, string(b))
Defensive patterns

Strategy: type-guard

Validate before calling

func isWritable(v interface{}) bool {
    rv := reflect.ValueOf(v)
    for rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Slice { rv = rv.Elem() }
    switch rv.Kind() {
    case reflect.String, reflect.Int, reflect.Float64, reflect.Bool, reflect.Struct:
        return true
    }
    return false
}

Type guard

func writableKind(v interface{}) (reflect.Kind, bool) {
    rv := reflect.ValueOf(v)
    for rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Slice { rv = rv.Elem() }
    switch rv.Kind() {
    case reflect.String, reflect.Int, reflect.Float64, reflect.Bool, reflect.Struct:
        return rv.Kind(), true
    }
    return rv.Kind(), false
}

Try / catch

quads, err := w.WriteAsQuads(qs, val)
if err != nil {
    if strings.Contains(err.Error(), "unsupported type:") {
        // convert maps/complex types to strings or structs first
    }
    return err
}

Prevention

When it happens

Trigger: Writing a value to the graph (via Writer/WriteAsQuads or schema write path) whose resolved kind is a map, channel, complex number, interface, or other non-struct non-scalar type.

Common situations: Attempting to store map[string]interface{} payloads; writing complex128 or chan fields; passing nil-interface values into the writer.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06). Data as JSON: /api/errors/463f45324471eac1. Report an issue: GitHub.