dgraph-io/dgraph · error

Field in type definition cannot have tokenizers

Error message

Field in type definition cannot have tokenizers

What it means

typeSanityCheck rejects type-definition fields that specify tokenizers. Tokenizers (hash, exact, term, fulltext, etc.) control indexing at the predicate level; a type definition only lists which predicates belong to the type, so attaching tokenizers there is invalid and the whole type update is refused.

Solutions

  1. Strip tokenizers from the type block and declare them on the predicate line instead: `name: string @index(hash) .`
  2. Ensure schema-generation code creates separate pb.SchemaUpdate entries for predicates (with Tokenizer) and types (with Tokenizer empty)
  3. Re-send the alter request after separating predicate schema from type definitions

Example fix

// before
type Person {
  name @index(hash)
}
// after
name: string @index(hash) .
type Person {
  name
}
Defensive patterns

Strategy: validation

Validate before calling

for _, f := range typeDef.Fields {
    if len(f.Tokenizer) > 0 {
        return fmt.Errorf("field %q: tokenizers must be declared on the predicate", f.Predicate)
    }
}

Type guard

func fieldHasNoTokenizer(f *pb.SchemaUpdate) bool {
    return len(f.Tokenizer) == 0
}

Prevention

When it happens

Trigger: An alter/schema request where a field inside a `type` block has a non-empty Tokenizer array — usually because schema-building code copies pb.SchemaUpdate entries built for predicates (which carry tokenizers) into type definitions.

Common situations: Reusing one schema JSON/struct for both predicate and type definitions; migrating from predicate-centric tooling and forgetting tokenizers are not part of type blocks; hand-written DQL placing tokenizers inside type blocks.

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/f100fbeac5ee7258. Report an issue: GitHub.

Appendix: source

Thrown at worker/mutation.go:835

// typeSanityCheck performs basic sanity checks on the given type update.
func typeSanityCheck(t *pb.TypeUpdate) error {
	for _, field := range t.Fields {
		if x.ParseAttr(field.Predicate) == "" {
			return errors.Errorf("Field in type definition must have a name")
		}

		if field.ValueType == pb.Posting_OBJECT && field.ObjectTypeName == "" {
			return errors.Errorf(
				"Field with value type OBJECT must specify the name of the object type")
		}

		if field.Directive != pb.SchemaUpdate_NONE {
			return errors.Errorf("Field in type definition cannot have a directive")
		}

		if len(field.Tokenizer) > 0 {
			return errors.Errorf("Field in type definition cannot have tokenizers")
		}
	}

	return nil
}

// CommitOverNetwork makes a proxy call to Zero to commit or abort a transaction.
func CommitOverNetwork(ctx context.Context, tc *api.TxnContext) (uint64, error) {
	ctx, span := otel.Tracer("").Start(ctx, "worker.CommitOverNetwork")
	defer span.End()

	clientDiscard := false
	if tc.Aborted {
		// The client called Discard
		ostats.Record(ctx, x.TxnDiscards.M(1))
		clientDiscard = true
	}

View on GitHub (pinned to 759e242be6)