{"record":{"id":"586d2439f88fe306","repo":"dgraph-io/dgraph","slug":"field-s-cannot-be-empty","errorCode":null,"errorMessage":"field %s cannot be empty","messagePattern":"field (.+?) cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/resolve/mutation_rewriter.go","lineNumber":1573,"sourceCode":"\t\t\t\txidType := xid.Type().String()\n\t\t\t\tif xidVal, ok := obj[xid.Name()]; ok && xidVal != nil {\n\t\t\t\t\t// This is handled in the for loop above\n\t\t\t\t\tcontinue\n\t\t\t\t} else if (mutationType == Add || mutationType == AddWithUpsert || !atTopLevel) &&\n\t\t\t\t\t(xidType == \"String!\" || xidType == \"Int!\" || xidType == \"Int64!\") {\n\t\t\t\t\t// When we reach this stage we are absolutely sure that this is not a reference and is\n\t\t\t\t\t// a new node and one of the XIDs is missing.\n\t\t\t\t\t// There are two possibilities here:\n\t\t\t\t\t// 1. This is an Add Mutation or we are at some deeper level inside Update Mutation:\n\t\t\t\t\t//    In this case this is an error as XID field if referenced anywhere inside Add Mutation\n\t\t\t\t\t//    or at deeper levels in Update Mutation has to be present. If multiple xids are not present\n\t\t\t\t\t//    then we return error for only one.\n\t\t\t\t\t// 2. This is an Update Mutation and we are at top level:\n\t\t\t\t\t//    In this case this is not an error as the UID at top level of Update Mutation is\n\t\t\t\t\t//    referenced as uid(x) in mutations. We don't throw an error in this case and continue\n\t\t\t\t\t//    with the function.\n\n\t\t\t\t\terr := errors.Errorf(\"field %s cannot be empty\", xid.Name())\n\t\t\t\t\tretErrors = append(retErrors, err)\n\t\t\t\t\treturn nil, upsertVar, retErrors\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\taction := defaultDirectiveUpdateAct\n\n\t// This is not an XID reference. This is also not a UID reference.\n\t// This is definitely a new node.\n\t// Create new node\n\tif variable == \"\" {\n\t\t// This will happen in case when this is a new node and does not contain XID.\n\t\tvariable = varGen.Next(typ, \"\", \"\", false)\n\t}\n\n\t// myUID is used for referencing this node. It is set to _:variable","sourceCodeStart":1555,"sourceCodeEnd":1591,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/resolve/mutation_rewriter.go#L1555-L1591","documentation":"A field marked with @id (external ID / XID) was provided with an empty value in a mutation. Dgraph requires @id fields to carry a non-empty value because they are used for existence queries and node references. This variant is thrown for objects in mutation input where the XID field resolved to an empty value.","triggerScenarios":"Sending an add or update mutation whose nested input object includes an @id field (e.g. `username`) set to \"\", or where the client omitted a value but the field object was still constructed and passed to the rewriter.","commonSituations":"Client forms submitting blank strings instead of omitting the field, deserialization frameworks materializing empty strings for missing values, or template-driven mutations interpolating an empty variable.","solutions":["Omit the @id field entirely from the mutation input when no value is available, instead of sending an empty string.","Send null or drop the field in client code before serializing the GraphQL request.","If the field should be optional, remove the @id directive from the schema and redeploy it.","Validate input on the client: reject empty strings for fields declared with @id."],"exampleFix":"// before\naddUser(input: { name: \"Bob\", username: \"\" })\n// after\naddUser(input: { name: \"Bob\" }) // omit the empty @id field","handlingStrategy":"validation","validationCode":"const xidFields = [\"username\", \"email\"];\nfunction assertNoEmptyXids(input) {\n  for (const f of xidFields) {\n    if (input[f] === \"\") throw new Error(`field ${f} cannot be empty; omit it or provide a value`);\n  }\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await client.mutate({ mutation: ADD_USER, variables: { input } });\n} catch (e) {\n  if (/field \\w+ cannot be empty/.test(e.message)) {\n    const field = e.message.match(/field (\\w+)/)[1];\n    delete input[Object.keys(input).find(k => k === field)];\n  } else throw e;\n}","preventionTips":["Strip empty strings from mutation payloads before sending.","Validate @id fields with a non-empty-string check on the client.","Only mark fields @id in the schema if they are truly mandatory identifiers.","Normalize form submissions: convert '' to undefined."],"tags":["graphql","mutation","empty-value"],"backgroundTag":"empty-required-field","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}