dgraph-io/dgraph · error

Index not allowed on predicate of type uid on predicate %s

Error message

Index not allowed on predicate of type uid on predicate %s

What it means

Dgraph does not support indexing on predicates whose value type is uid, because uid edges are already stored in an indexed (postings-list) form. checkSchema rejects any update where ValueType is UidID and Directive is SchemaUpdate_INDEX, naming the offending predicate.

Source

Thrown at worker/mutation.go:404

	}

	if x.IsInternalPredicate(s.Predicate) {
		return errors.Errorf("Cannot create user-defined predicate with internal name %s",
			x.ParseAttr(s.Predicate))
	}

	if s.Directive == pb.SchemaUpdate_INDEX && !schema.HasTokenizerOrVectorIndexSpec(s) {
		return errors.Errorf("Tokenizer must be specified while indexing a predicate: %+v", s)
	}

	if schema.HasTokenizerOrVectorIndexSpec(s) && s.Directive != pb.SchemaUpdate_INDEX {
		return errors.Errorf("Directive must be SchemaUpdate_INDEX when a tokenizer is specified")
	}

	typ := types.TypeID(s.ValueType)
	if typ == types.UidID && s.Directive == pb.SchemaUpdate_INDEX {
		// index on uid type
		return errors.Errorf("Index not allowed on predicate of type uid on predicate %s",
			x.ParseAttr(s.Predicate))
	} else if typ != types.UidID && s.Directive == pb.SchemaUpdate_REVERSE {
		// reverse on non-uid type
		return errors.Errorf("Cannot reverse for non-uid type on predicate %s",
			x.ParseAttr(s.Predicate))
	}

	// If schema update has upsert directive, it should have index directive.
	if s.Upsert && len(s.Tokenizer) == 0 && !s.Unique {
		return errors.Errorf("Index tokenizer is mandatory for: [%s] when specifying @upsert directive",
			x.ParseAttr(s.Predicate))
	}

	if s.Unique {
		ctx := context.WithValue(context.Background(), schema.IsWrite, false)
		prevSchema, _ := schema.State().Get(ctx, s.Predicate)
		if err := validateSchemaForUnique(prevSchema, s); err != nil {
			return err

View on GitHub (pinned to 759e242be6)

Solutions

  1. Remove the @index directive from the uid predicate: 'friend: [uid] @reverse'.
  2. If fast lookup is needed on a uid edge, use @reverse instead of @index.
  3. If the predicate should hold values other than uids, change its type to a scalar type (string, int, etc.) and keep the tokenizer.
  4. Filter uid-typed predicates out of index-directive generation in schema tooling.

Example fix

// before
friend: [uid] @index(term) .
// after
friend: [uid] @reverse .
Defensive patterns

Strategy: validation

Validate before calling

func validateNoIndexOnUid(s *pb.SchemaUpdate) error {
    if types.TypeID(s.ValueType) == types.UidID && s.Directive == pb.SchemaUpdate_INDEX {
        return fmt.Errorf("predicate %s: @index not allowed on uid", s.Predicate)
    }
    return nil
}

Type guard

func isUidPredicate(s *pb.SchemaUpdate) bool {
    return types.TypeID(s.ValueType) == types.UidID
}

Try / catch

err := dgraph.Alter(ctx, op)
if err != nil && strings.Contains(err.Error(), "Index not allowed on predicate of type uid") {
    // remove @index, use @reverse instead
}

Prevention

When it happens

Trigger: Declaring or altering a uid predicate with an index directive, e.g. 'friend: [uid] @index(hash)' in a DQL schema, or constructing pb.SchemaUpdate with ValueType: pb.Posting_UID and Directive: pb.SchemaUpdate_INDEX.

Common situations: Copy-pasting '@index(term) or @index(hash)' across all predicates in a generated schema without excluding uid predicates; misunderstanding that @reverse suffices for uid edges; template-based schema tooling applying uniform directives.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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