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
- Mutate with an actual UID reference, e.g. `<0x1> <friend> <0x2> .` or use `<friend> * * .` expansions correctly.
- 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) . } } }`.
- 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
- For uid predicates, always send node references, blank nodes, or uid() expressions — never literals.
- Use upsert blocks with eq() lookups to map external IDs to UIDs.
- Check the schema (schema{}) before generating mutations so types are known.
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
- Input for predicate %q of type scalar is uid. Edge: %v
- UID must to be greater than 0
- Input for predicate %q of type vector is not vector. Did you
- UID must be present and non-zero while deleting edges
- facet value can only be string/number/bool
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/fff468b55e1ef745.
Report an issue: GitHub.