dgraph-io/dgraph · error

id is not provided

Error message

id is not provided

What it means

Within an Update mutation's remove path, nested nodes must be identified by an ID (UID) or an @id/XID so Dgraph knows which edges to remove. If a nested object in a remove operation carries neither, Dgraph cannot infer the target and throws this error. Add mutations legitimately create blank nodes, but remove cannot.

Source

Thrown at graphql/resolve/mutation_rewriter.go:1621

		// Case 1:
		// It's an update and we are at top level. So, the UID of node(s) for which
		// we are rewriting is/are referenced using "uid(x)" as part of mutations.
		// We don't need to create a new blank node in this case.
		// srcUID is equal to uid(x) in this case.
		// Case 2:
		// This is an upsert with Add Mutation and upsertVar is non-empty (which means
		// the XID at top level exists and this is an upsert).
		// We continue updating in this case and no new node is created. srcUID will be
		// equal to uid(variable) in this case. Eg. uid(State1)
		newObj["uid"] = srcUID
		myUID = srcUID
	} else if mutationType == UpdateWithRemove {
		// It's a remove. As remove can only be part of Update Mutation. It can
		// be inferred that this is an Update Mutation.
		// In case of remove of Update, deeper level nodes have to be referenced by ID
		// or XID. If we have reached this stage, we can be sure that no such reference
		// to ID or XID exists. In that case, we throw an error.
		err := errors.Errorf("id is not provided")
		retErrors = append(retErrors, err)
		return nil, upsertVar, retErrors
	} else {
		// We are in Add Mutation or at a deeper level in Update Mutation set.
		// If we have reached this stage, we can be sure that we need to create a new
		// node as part of the mutation. The new node is referenced as a blank node like
		// "_:Project2" . myUID will store the variable generated to reference this node.
		newObj["dgraph.type"] = dgraphTypes
		newObj["uid"] = myUID
		action = defaultDirectiveAddAct
	}

	// Now we know whether this is a new node or not, we can set @default(add/update) fields
	for _, field := range typ.Fields() {
		var pred = field.DgraphPredicate()
		if newObj[pred] != nil {
			continue
		}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Include the node's `id` (UID) in each nested object within the remove input.
  2. Alternatively include the @id/XID field value so the node can be resolved by external ID.
  3. If the intent is to clear the whole edge, pass null (or the appropriate scalar) instead of an empty object.
  4. Review the generated mutation payload to ensure the remove branch mirrors the identifier present in the add/set branch.

Example fix

// before
updatePost(input: { filter: { id: ["0x1"] }, remove: { author: {} } })
// after
updatePost(input: { filter: { id: ["0x1"] }, remove: { author: { id: "0x2" } } })
Defensive patterns

Strategy: validation

Validate before calling

function assertRemovable(node) {
  if (node == null || typeof node !== 'object') return;
  if (!('id' in node) && node.id == null && !hasXidField(node)) {
    throw new Error("remove input needs an id or @id value");
  }
}
function hasXidField(node) {
  return Object.entries(node).some(([k, v]) => k !== 'id' && v !== '' && v != null);
}

Type guard

function isIdentifiableNode(n) {
  return typeof n === 'object' && n !== null && (('id' in n) || ('username' in n));
}

Try / catch

try {
  await client.mutate({ mutation: UPDATE_POST, variables: { input } });
} catch (e) {
  if (/id is not provided/.test(e.message)) {
    // add id or @id value to every nested object in the remove payload
  } else throw e;
}

Prevention

When it happens

Trigger: Calling an update mutation with a remove input (e.g. updatePost(remove: { author: {} })) where a nested object contains no `id` field and no @id/XID field.

Common situations: Client code building remove payloads from partially filled objects, forgetting to include the identifier when only sending the fields to unlink, or schemas where the nested type's XID field was renamed.

Related errors


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