{"record":{"id":"f3bfdac39d5e06ac","repo":"dgraph-io/dgraph","slug":"while-upserting-user-with-id-s-f3bfda","errorCode":null,"errorMessage":"While upserting user with id %s","messagePattern":"While upserting user with id (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"edgraph/access.go","lineNumber":599,"sourceCode":"\tif len(userResp.GrootUser) == 0 {\n\t\t// no groot user found from query\n\t\t// Extract uid of created groot user from mutation\n\t\tnewUserUidMap := resp.GetUids()\n\t\tgrootUserUid = newUserUidMap[\"newuser\"]\n\t} else if len(userResp.GrootUser) == 1 {\n\t\t// we found a groot user\n\t\tgrootUserUid = userResp.GrootUser[0].Uid\n\t} else {\n\t\treturn errors.Wrap(err, \"Multiple groot users found\")\n\t}\n\n\tuid, err := strconv.ParseUint(grootUserUid, 0, 64)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"Error while parsing Uid: %s of groot user\", grootUserUid)\n\t}\n\tns, err := x.ExtractNamespace(ctx)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"While upserting user with id %s\", x.GrootId)\n\t}\n\tx.GrootUid.Store(ns, uid)\n\tglog.V(2).Infof(\"Successfully upserted groot account for namespace %d\\n\", ns)\n\treturn nil\n}\n\n// extract the userId, groupIds from the accessJwt in the context\nfunc extractUserAndGroups(ctx context.Context) (*userData, error) {\n\taccessJwt, err := x.ExtractJwt(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn validateToken(accessJwt)\n}\n\ntype authPredResult struct {\n\tallowed []string\n\tblocked map[string]struct{}","sourceCodeStart":581,"sourceCodeEnd":617,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/edgraph/access.go#L581-L617","documentation":"upsertGroot extracts the namespace from the request context via x.ExtractNamespace(ctx) and wraps any failure with 'While upserting user with id %s' (id = x.GrootId). The namespace header (AccessJwt-Namespace) is missing or malformed in the internal context used for groot upsert.","triggerScenarios":"Calling any ACL bootstrapping/admin operation whose context lacks a valid namespace value — e.g. health checking, Reset, or Guardian operations issued without the namespace header or with a malformed one.","commonSituations":"Client/proxy stripping the AccessJwt-Namespace header; connecting with an old client SDK that doesn't send namespace info; calling admin endpoints cross-namespace.","solutions":["Ensure the client sends the correct AccessJwt-Namespace (or use a current dgraph client that does)","Use the superadmin namespace (0) for groot/guardian operations","Upgrade the dgraph Go client/grpclient if it predates namespace support","Check that a proxy (e.g. nginx/grpc-web) isn't dropping metadata headers"],"exampleFix":"// before\nconn, _ := grpc.Dial(addr)\nc := api.NewDgraphClient(conn)\nc.Reset(ctx)\n// after\nctx = metadata.AppendToOutgoingContext(ctx, \"AccessJwt-Namespace\", \"0\")\nc.Reset(ctx)","handlingStrategy":"validation","validationCode":"// Attach namespace metadata before any admin/ACL call\nimport { Metadata } from '@grpc/grpc-js'\nconst md = new Metadata()\nmd.add('AccessJwt-Namespace', String(namespace)) // e.g. '0' for superadmin\nif (!namespace || isNaN(Number(namespace))) {\n  throw new Error('valid namespace required for groot operations')\n}","typeGuard":"function hasNamespace(ctx) {\n  return ctx != null && Number.isInteger(Number(ctx.namespace))\n}","tryCatchPattern":null,"preventionTips":["Use an up-to-date dgraph client that sends namespace headers automatically","Route admin calls directly to Alphas, not through header-stripping proxies","Default to namespace 0 for guardian/groot operations"],"tags":["namespace","context","grpc","acl"],"backgroundTag":"missing-namespace-header","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}