dgraph-io/dgraph · error
ID "%s" isn't a %s
Error message
ID "%s" isn't a %s
What it means
During GraphQL mutation rewriting, a node referenced by its UID (ID field) was checked against the results of existence queries and no node with that UID exists in the database. Since referenced nodes must already exist, Dgraph rejects the mutation rather than silently creating a dangling reference. The error names the offending ID value and the expected type name.
Source
Thrown at graphql/resolve/mutation_rewriter.go:1393
// We return an error if this is at toplevel. Else, we return the ID reference
if atTopLevel {
// We need to conceal the error because we might be leaking information to the user if it
// tries to add duplicate data to the field with @id.
var err error
if queryAuthSelector(typ) == nil {
err = x.GqlErrorf("id %s already exists for type %s", idVal.(string), typ.Name())
} else {
// This error will only be reported in debug mode.
err = x.GqlErrorf("GraphQL debug: id already exists for type %s", typ.Name())
}
retErrors = append(retErrors, err)
return nil, upsertVar, retErrors
} else {
return asIDReference(ctx, idVal, srcField, srcUID, varGen, mutationType == UpdateWithRemove), upsertVar, nil
}
} else {
// Reference UID does not exist. This is an error.
err := errors.Errorf("ID \"%s\" isn't a %s", idVal.(string), srcField.Type().Name())
retErrors = append(retErrors, err)
return nil, upsertVar, retErrors
}
}
}
xids := typ.XIDFields()
if len(xids) != 0 {
// multipleNodesForSameID is true when there are multiple nodes present
// in a result of existence queries
multipleNodesForSameID := gotMultipleExistingNodes(xids, obj, typ, varGen, idExistence)
// xidVariables stores the variable names for each XID.
var xidVariables []string
for _, xid := range xids {
var xidString string
if xidVal, ok := obj[xid.Name()]; ok && xidVal != nil {
xidString, _ = extractVal(xidVal, xid.Name(), xid.Type().Name())
variable = varGen.Next(typ, xid.Name(), xidString, false)View on GitHub (pinned to 759e242be6)
Solutions
- Query the node by that UID first to confirm it exists; create it (or use an upsert mutation with @id/XID) before referencing it.
- Use the node's external ID (XID) instead of the raw UID so Dgraph can run an existence query and reference or upsert correctly.
- Fix stale references in fixtures/seed data by regenerating UIDs from the target environment.
- Check the mutation structure: an ID reference at the top level of an Update mutation is allowed, but nested references must point to existing nodes.
Example fix
// before
addPost(input: { title: "hi", author: { id: "0x1234" } }) // 0x1234 does not exist
// after
addPost(input: { title: "hi", author: { username: "alice" } }) // reference via @id field, or create the author first Defensive patterns
Strategy: validation
Validate before calling
async function uidExists(dgraph, uid, typeName) {
const q = `query { n(func: uid(${uid})) @filter(type(${typeName})) { uid } }`;
const res = await dgraph.newTxn().query(q);
return res.data.n.length > 0;
}
// before the mutation: if (!(await uidExists(client, input.author.id, "Author"))) throw new Error("referenced Author does not exist"); Type guard
function isValidUid(v) {
return typeof v === 'string' && /^0x[0-9a-fA-F]+$/.test(v);
} Try / catch
try {
await client.mutate({ mutation: ADD_POST, variables: { input } });
} catch (e) {
if (/ID \".*\" isn't a/.test(e.message)) {
// create the referenced node or switch to an @id/XID reference
} else throw e;
} Prevention
- Query existence of UIDs before referencing them in nested mutations.
- Prefer @id/XID references over raw UIDs in application code.
- Never copy UIDs between environments; regenerate fixtures per environment.
- Use upsert blocks when you want create-or-reference semantics.
When it happens
Trigger: Calling an add/update mutation (e.g. addPost with set/add or update with a nested reference) where a nested object supplies an `id` field whose UID does not exist in Dgraph, and the mutation is not at top level (so it cannot be treated as an upsert/create).
Common situations: Hardcoded or copied UIDs from another environment (dev vs prod), deleted nodes still referenced by client code, stale test fixtures, or typos/truncation in a UID string.
Related errors
- can't convert input to map
- can't convert input.what to string
- can't convert input to map
- can't convert input to map
- not able to find set args in update mutation
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/0dd2a2aea1196118.
Report an issue: GitHub.