{"record":{"id":"82363a5b9716877b","repo":"cayleygraph/cayley","slug":"wrong-quad-tag-format-s","errorCode":null,"errorMessage":"wrong quad tag format: '%s'","messagePattern":"wrong quad tag format: '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"schema/schema.go","lineNumber":176,"sourceCode":"\t\t}\n\t\tif s == \"req\" || s == \"required\" {\n\t\t\treq = true\n\t\t}\n\t}\n\tif req {\n\t\topt = false\n\t} else if fld.Type.Kind() == reflect.Slice {\n\t\topt = true\n\t}\n\n\trev := strings.Contains(rule, ops)\n\tvar tri []string\n\tif jsn {\n\t\ttri = []string{rule}\n\t} else if rev { // o<p-s\n\t\ttri = strings.SplitN(rule, ops, 3)\n\t\tif len(tri) != 2 {\n\t\t\treturn nil, fmt.Errorf(\"wrong quad tag format: '%s'\", rule)\n\t\t}\n\t} else { // s-p>o // default\n\t\ttri = strings.SplitN(rule, spo, 3)\n\t\tif len(tri) > 2 { //len(tri) != 2 {\n\t\t\treturn nil, fmt.Errorf(\"wrong quad tag format: '%s'\", rule)\n\t\t}\n\t}\n\tvar ps, vs string\n\tif rev {\n\t\tps, vs = strings.Trim(tri[0], trim), strings.Trim(tri[1], trim)\n\t} else {\n\t\tps, vs = strings.Trim(tri[0], trim), any\n\t\tif len(tri) > 1 {\n\t\t\tvs = strings.Trim(tri[1], trim)\n\t\t}\n\t}\n\tif ps == \"\" {\n\t\treturn nil, fmt.Errorf(\"wrong quad format: '%s': no predicate\", rule)","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/schema/schema.go#L158-L194","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Validate the tag string (count separators) before calling AddType.","Compare against working rule examples in the schema package tests."],"exampleFix":"// before\nc.AddType(Person{}, \"friend<\") // malformed reverse rule\n// after\nc.AddType(Person{}, \"<friend\") // correct reverse form: o<p","handlingStrategy":"validation","validationCode":"func validReverseRule(rule string) bool {\n    parts := strings.SplitN(rule, \"<\", 3)\n    return len(parts) == 2 && strings.TrimSpace(parts[0]) != \"\" && strings.TrimSpace(parts[1]) != \"\"\n}\nif !validReverseRule(tag) { /* fix before AddType */ }","typeGuard":"func isWellFormedQuadTag(rule string) bool {\n    if strings.Contains(rule, \"<\") {\n        return len(strings.SplitN(rule, \"<\", 3)) == 2\n    }\n    return len(strings.SplitN(rule, \">\", 3)) <= 2\n}","tryCatchPattern":"if err := c.AddType(t, tag); err != nil {\n    if strings.Contains(err.Error(), \"wrong quad tag format\") {\n        return fmt.Errorf(\"schema rule %q malformed: %w\", tag, err)\n    }\n    return err\n}","preventionTips":["Validate rule strings with the same SplitN logic the library uses, before AddType.","Keep reverse-rule syntax documented in your schema definitions.","Add table-driven tests covering each rule format."],"tags":["go","schema","quad-tag","syntax"],"backgroundTag":"invalid-argument-format","analyzedSha":"81dcd7d73e45136bc0d01802a8ba4685d8a533eb","analyzedAt":"2026-09-06T06:14:12.358Z","contentChangedAt":"2026-09-06T06:14:12.358Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}