dgraph-io/dgraph · error

value for field `%s` in type `%s` must have exactly one chil

Error message

value for field `%s` in type `%s` must have exactly one child, found %d children

What it means

Same condition as the indexed variant: a value for a field must have exactly one child, but Dgraph found a different number. This variant is used when the offending value is not inside a list context (listIndex < 0), so no index is reported. The field name, parent type, and actual child count are included.

Source

Thrown at graphql/resolve/mutation_rewriter.go:2035

	ctx context.Context,
	parentTyp schema.Type,
	srcField schema.FieldDefinition,
	varGen *VariableGenerator,
	obj map[string]interface{},
	xidMetadata *xidMetadata,
	listIndex int) ([]*dql.GraphQuery, []string, []error) {

	var retError []error
	if len(obj) != 1 {
		var err error
		// if this was called from rewriteList,
		// the listIndex will tell which particular item in the list has an error.
		if listIndex >= 0 {
			err = fmt.Errorf(
				"value for field `%s` in type `%s` index `%d` must have exactly one child, "+
					"found %d children", srcField.Name(), parentTyp.Name(), listIndex, len(obj))
		} else {
			err = fmt.Errorf(
				"value for field `%s` in type `%s` must have exactly one child, found %d children",
				srcField.Name(), parentTyp.Name(), len(obj))
		}
		retError = append(retError, err)
		return nil, nil, retError
	}

	var newtyp schema.Type
	for memberRef, memberRefVal := range obj {
		memberTypeName := strings.ToUpper(memberRef[:1]) + memberRef[1:len(
			memberRef)-3]
		srcField = srcField.WithMemberType(memberTypeName)
		newtyp = srcField.Type()
		obj = memberRefVal.(map[string]interface{})
	}
	return existenceQueries(ctx, newtyp, srcField, varGen, obj, xidMetadata)
}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Reshape the field value so it contains exactly one child object (one node with its fields).
  2. Remove unexpected sibling keys from the nested object.
  3. Ensure a nested node object is non-empty and identified via id or @id fields.
  4. Use a typed GraphQL client to construct the payload and catch structural mistakes at build time.

Example fix

// before
author: { name: "A", username: "x", extra: 1 } // 3 children
// after
author: { name: "A", username: "x" } // valid single node value
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleChild(value, field) {
  if (typeof value === 'object' && value !== null && Object.keys(value).length !== 1) {
    throw new Error(`field ${field} must have exactly one child, found ${Object.keys(value).length}`);
  }
}

Type guard

function isSingleChildNode(v) {
  return typeof v === 'object' && v !== null && Object.keys(v).length === 1;
}

Try / catch

try {
  await client.mutate({ mutation: ADD, variables: { input } });
} catch (e) {
  if (/must have exactly one child/.test(e.message)) {
    const f = e.message.match(/field `(\w+)`/)[1];
    console.warn("reshape nested value for field", f);
  } else throw e;
}

Prevention

When it happens

Trigger: A nested object in an add/update mutation where a field's value is an object containing zero or more than one child key when exactly one nested node was expected — outside of list rewriting.

Common situations: Copy-paste errors in nested mutation payloads, code generators emitting wrapper objects with extra metadata keys, or clients sending `{}` for a required nested node.

Related errors


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