{"record":{"id":"eba07a456dbf8705","repo":"dgraph-io/dgraph","slug":"cannot-reverse-for-non-uid-type-on-predicate-s","errorCode":null,"errorMessage":"Cannot reverse for non-uid type on predicate %s","messagePattern":"Cannot reverse for non-uid type on predicate (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"worker/mutation.go","lineNumber":408,"sourceCode":"\t\t\tx.ParseAttr(s.Predicate))\n\t}\n\n\tif s.Directive == pb.SchemaUpdate_INDEX && !schema.HasTokenizerOrVectorIndexSpec(s) {\n\t\treturn errors.Errorf(\"Tokenizer must be specified while indexing a predicate: %+v\", s)\n\t}\n\n\tif schema.HasTokenizerOrVectorIndexSpec(s) && s.Directive != pb.SchemaUpdate_INDEX {\n\t\treturn errors.Errorf(\"Directive must be SchemaUpdate_INDEX when a tokenizer is specified\")\n\t}\n\n\ttyp := types.TypeID(s.ValueType)\n\tif typ == types.UidID && s.Directive == pb.SchemaUpdate_INDEX {\n\t\t// index on uid type\n\t\treturn errors.Errorf(\"Index not allowed on predicate of type uid on predicate %s\",\n\t\t\tx.ParseAttr(s.Predicate))\n\t} else if typ != types.UidID && s.Directive == pb.SchemaUpdate_REVERSE {\n\t\t// reverse on non-uid type\n\t\treturn errors.Errorf(\"Cannot reverse for non-uid type on predicate %s\",\n\t\t\tx.ParseAttr(s.Predicate))\n\t}\n\n\t// If schema update has upsert directive, it should have index directive.\n\tif s.Upsert && len(s.Tokenizer) == 0 && !s.Unique {\n\t\treturn errors.Errorf(\"Index tokenizer is mandatory for: [%s] when specifying @upsert directive\",\n\t\t\tx.ParseAttr(s.Predicate))\n\t}\n\n\tif s.Unique {\n\t\tctx := context.WithValue(context.Background(), schema.IsWrite, false)\n\t\tprevSchema, _ := schema.State().Get(ctx, s.Predicate)\n\t\tif err := validateSchemaForUnique(prevSchema, s); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tt, err := schema.State().TypeOf(s.Predicate)","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/worker/mutation.go#L390-L426","documentation":"The @reverse directive (storing uid -> owning-node reverse edges) is only meaningful for predicates whose values are uids. checkSchema rejects updates where the value type is not uid but Directive is SchemaUpdate_REVERSE, e.g. putting @reverse on a string or int predicate.","triggerScenarios":"Altering a scalar predicate with @reverse, e.g. 'age: int @reverse', or building pb.SchemaUpdate with ValueType != Posting_UID and Directive: pb.SchemaUpdate_REVERSE.","commonSituations":"Bulk-adding @reverse to every predicate in a schema; expecting reverse traversal on scalar fields; IDE autocomplete or tooling that appends directives indiscriminately.","solutions":["Remove @reverse from the scalar predicate.","If reverse traversal is genuinely needed, model the relationship as a uid edge instead of a scalar value.","Only apply @reverse to predicates declared as uid (e.g. 'author: [uid] @reverse').","Add a pre-flight check that Directive==REVERSE implies ValueType==UID in schema-generation code."],"exampleFix":"// before\nage: int @reverse .\n// after\nage: int .","handlingStrategy":"validation","validationCode":"func validateReverseOnUid(s *pb.SchemaUpdate) error {\n    if types.TypeID(s.ValueType) != types.UidID && s.Directive == pb.SchemaUpdate_REVERSE {\n        return fmt.Errorf(\"predicate %s: @reverse only valid on uid\", s.Predicate)\n    }\n    return nil\n}","typeGuard":"func canReverse(s *pb.SchemaUpdate) bool {\n    return types.TypeID(s.ValueType) == types.UidID && s.Directive == pb.SchemaUpdate_REVERSE\n}","tryCatchPattern":"err := dgraph.Alter(ctx, op)\nif err != nil && strings.Contains(err.Error(), \"Cannot reverse for non-uid type\") {\n    // drop @reverse from the predicate\n}","preventionTips":["Only add @reverse to uid-typed predicates","Lint schema files: flag @reverse on scalar types","Model reverse lookups on scalars with a uid edge instead"],"tags":["dgraph","schema","uid","reverse"],"backgroundTag":"schema-validation-failed","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}