cayleygraph/cayley · error

wrong quad tag format: '%s'

Error message

wrong quad tag format: '%s'

What it means

getStepTypeClasses parses a schema rule tag to determine subject-predicate-object classes. For a reverse rule ("o<p-s" form) the tag must split on the operator into exactly 2 parts; if SplitN doesn't yield 2 parts, the tag is malformed and this error is returned to AddType.

Source

Thrown at schema/schema.go:176

		}
		if s == "req" || s == "required" {
			req = true
		}
	}
	if req {
		opt = false
	} else if fld.Type.Kind() == reflect.Slice {
		opt = true
	}

	rev := strings.Contains(rule, ops)
	var tri []string
	if jsn {
		tri = []string{rule}
	} else if rev { // o<p-s
		tri = strings.SplitN(rule, ops, 3)
		if len(tri) != 2 {
			return nil, fmt.Errorf("wrong quad tag format: '%s'", rule)
		}
	} else { // s-p>o // default
		tri = strings.SplitN(rule, spo, 3)
		if len(tri) > 2 { //len(tri) != 2 {
			return nil, fmt.Errorf("wrong quad tag format: '%s'", rule)
		}
	}
	var ps, vs string
	if rev {
		ps, vs = strings.Trim(tri[0], trim), strings.Trim(tri[1], trim)
	} else {
		ps, vs = strings.Trim(tri[0], trim), any
		if len(tri) > 1 {
			vs = strings.Trim(tri[1], trim)
		}
	}
	if ps == "" {
		return nil, fmt.Errorf("wrong quad format: '%s': no predicate", rule)

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Fix the rule so it has exactly one reverse operator: "o<p-s" form with predicate and value, e.g. "<follows" style rules matching the expected 2-part split.
  2. Validate the tag string (count separators) before calling AddType.
  3. Compare against working rule examples in the schema package tests.

Example fix

// before
c.AddType(Person{}, "friend<") // malformed reverse rule
// after
c.AddType(Person{}, "<friend") // correct reverse form: o<p
Defensive patterns

Strategy: validation

Validate before calling

func validReverseRule(rule string) bool {
    parts := strings.SplitN(rule, "<", 3)
    return len(parts) == 2 && strings.TrimSpace(parts[0]) != "" && strings.TrimSpace(parts[1]) != ""
}
if !validReverseRule(tag) { /* fix before AddType */ }

Type guard

func isWellFormedQuadTag(rule string) bool {
    if strings.Contains(rule, "<") {
        return len(strings.SplitN(rule, "<", 3)) == 2
    }
    return len(strings.SplitN(rule, ">", 3)) <= 2
}

Try / catch

if err := c.AddType(t, tag); err != nil {
    if strings.Contains(err.Error(), "wrong quad tag format") {
        return fmt.Errorf("schema rule %q malformed: %w", tag, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Config.AddType with a reverse-mapping quad tag string that doesn't contain exactly one reverse operator, e.g. missing separator or extra segments: "@rev<p" with no object part.

Common situations: Hand-written schema tags with typos in the '<' separator or reversed arrow; generating tags programmatically and joining with the wrong operator; copy-pasted rules missing a segment.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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