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.

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)

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.