dgraph-io/dgraph · error

Input for predicate %q of type uid is scalar. Edge: %v

Error message

Input for predicate %q of type uid is scalar. Edge: %v

What it means

The predicate's schema type is uid (a non-scalar/edge type), but the incoming mutation carries a scalar storage value (a literal, not a UID reference). ValidateAndConvert rejects this mismatch because a uid predicate can only be assigned node references.

Source

Thrown at worker/mutation.go:533

	if strings.Contains(su.Predicate, hnsw.VecKeyword) {
		return errors.Errorf("Not allowed to insert mutations in vector index keys, edge: [%v]", edge)
	}

	storageType := posting.TypeID(edge)
	schemaType := types.TypeID(su.ValueType)

	// type checks
	switch {
	case edge.Lang != "" && !su.GetLang():
		return errors.Errorf("Attr: [%v] should have @lang directive in schema to mutate edge: [%v]",
			x.ParseAttr(edge.Attr), edge)

	case !schemaType.IsScalar() && !storageType.IsScalar():
		return nil

	case !schemaType.IsScalar() && storageType.IsScalar():
		return errors.Errorf("Input for predicate %q of type uid is scalar. Edge: %v",
			x.ParseAttr(edge.Attr), edge)

	case schemaType.IsScalar() && !storageType.IsScalar():
		return errors.Errorf("Input for predicate %q of type scalar is uid. Edge: %v",
			x.ParseAttr(edge.Attr), edge)

	case schemaType == types.TypeID(pb.Posting_VFLOAT):
		if !(storageType == types.TypeID(pb.Posting_VFLOAT) || storageType == types.TypeID(pb.Posting_STRING) ||
			storageType == types.TypeID(pb.Posting_DEFAULT)) {
			return errors.Errorf("Input for predicate %q of type vector is not vector."+
				" Did you forget to add quotes before []?. Edge: %v", x.ParseAttr(edge.Attr), edge)
		}

	// The suggested storage type matches the schema, OK! (Nothing to do ...)
	case storageType == schemaType && schemaType != types.DefaultID:
		return nil

	// We accept the storage type iff we don't have a schema type and a storage type is specified.

View on GitHub (pinned to 759e242be6)

Solutions

  1. Mutate with an actual UID reference, e.g. `<0x1> <friend> <0x2> .` or use `<friend> * * .` expansions correctly.
  2. Use an upsert block with uid() to resolve identifiers to UIDs before linking: `upsert { query { f as var(func: eq(name, "alice")) } mutation { set { <0x1> <friend> uid(f) . } } }`.
  3. Fix the schema to a scalar type if the value is really an attribute, not a relationship.

Example fix

// before (fails; friend is uid)
<0x1> <friend> "alice" .

// after (upsert resolves name to uid)
upsert { query { f as var(func: eq(name, "alice")) }
  mutation { set { <0x1> <friend> uid(f) . } } }
Defensive patterns

Strategy: type-guard

Validate before calling

function assertUidObject(triple) {
  if (triple.predicateType === 'uid' && !/^<0x[0-9a-f]+>$|^_:[a-zA-Z0-9_]+$/.test(triple.object)) {
    throw new Error(`object must be a uid for ${triple.predicate}; got ${triple.object}`)
  }
}

Type guard

function isUidRef(v) {
  return typeof v === 'object' && v !== null &&
    (typeof v.uid === 'string' || typeof v.uid === 'number')
}

Try / catch

try {
  await txn.mutate(mu)
} catch (e) {
  if (String(e).includes('of type uid is scalar')) {
    // resolve identifier to a UID (upsert/uid()) and re-mutate
  }
}

Prevention

When it happens

Trigger: Running a mutation that assigns a literal value (string, number, default-typed value) to a predicate declared as `uid` in the schema, e.g. `<0x1> <friend> "alice" .` where friend is `friend: [uid]`.

Common situations: Using blank node or string identifiers without converting them to UIDs (e.g. via upsert or the <uid> placeholder in DQL); copy-pasted RDF that treats edges like attributes; client libraries serializing values as strings instead of UIDs.

Related errors


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