dgraph-io/dgraph · error

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

Error message

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

What it means

Mirror case of the scalar-for-uid error: the predicate's schema type is a scalar, but the mutation's storage value is a uid (node reference). ValidateAndConvert rejects the edge because a scalar predicate cannot hold node references.

Source

Thrown at worker/mutation.go:537

	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.
	case schemaType == types.DefaultID:
		schemaType = storageType
	}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Write a literal value matching the schema type, e.g. `<0x1> <age> "30"^^<xs:int> .`.
  2. If the relationship is real, change the schema to `age: [uid]` instead.
  3. Inspect the failing edge in the error message to see which side of the triple is wrong.

Example fix

// before (fails; age is int)
<0x1> <age> <0x2> .

// after
<0x1> <age> "30"^^<xs:int> .
Defensive patterns

Strategy: type-guard

Validate before calling

function assertScalarObject(triple, scalarType) {
  const isUidRef = typeof triple.object === 'object' && triple.object !== null && 'uid' in triple.object
  if (scalarType !== 'uid' && isUidRef) {
    throw new Error(`predicate ${triple.predicate} is ${scalarType}; object must be a literal`)
  }
}

Type guard

function isLiteral(v) {
  return typeof v !== 'object' || v === null || !('uid' in v)
}

Try / catch

try {
  await txn.mutate(mu)
} catch (e) {
  if (String(e).includes('of type scalar is uid')) {
    // either write a literal of the schema type, or change the schema to uid
  }
}

Prevention

When it happens

Trigger: Running a mutation that assigns a node (UID edge) to a predicate declared as a scalar type, e.g. `<0x1> <age> <0x2> .` where age is `int`, or listing a UID where the schema says string/float.

Common situations: Swapping subject/object in hand-written N-Quads; generating mutations programmatically and passing object UIDs into attribute predicates; schema changed to scalar after UIDs were already being written.

Related errors


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