{"record":{"id":"18651eaf26e63e8c","repo":"dgraph-io/dgraph","slug":"only-guardians-are-allowed-to-drop-all-data-but-t","errorCode":null,"errorMessage":"only guardians are allowed to drop all data, but the current user is %s","messagePattern":"only guardians are allowed to drop all data, but the current user is (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"edgraph/access.go","lineNumber":708,"sourceCode":"\t// as a byproduct, it also sets the userId, groups variables\n\tdoAuthorizeAlter := func() error {\n\t\tuserData, err := extractUserAndGroups(ctx)\n\t\tif err != nil {\n\t\t\t// We don't follow fail open approach anymore.\n\t\t\treturn status.Error(codes.Unauthenticated, err.Error())\n\t\t}\n\n\t\tuserId = userData.userId\n\t\tgroupIds = userData.groupIds\n\n\t\tif x.IsSuperAdmin(groupIds) {\n\t\t\t// Members of guardian group are allowed to alter anything.\n\t\t\treturn nil\n\t\t}\n\n\t\t// if we get here, we know the user is not a guardian.\n\t\tif isDropAll(op) || op.DropOp == api.Operation_DATA {\n\t\t\treturn errors.Errorf(\n\t\t\t\t\"only guardians are allowed to drop all data, but the current user is %s\", userId)\n\t\t}\n\n\t\tresult := authorizePreds(ctx, userData, preds, acl.Modify)\n\t\tif len(result.blocked) > 0 {\n\t\t\tvar msg strings.Builder\n\t\t\tfor key := range result.blocked {\n\t\t\t\tx.Check2(msg.WriteString(key))\n\t\t\t\tx.Check2(msg.WriteString(\" \"))\n\t\t\t}\n\t\t\treturn status.Errorf(codes.PermissionDenied,\n\t\t\t\t\"unauthorized to alter following predicates: %s\\n\", msg.String())\n\t\t}\n\t\treturn nil\n\t}\n\n\terr := doAuthorizeAlter()\n\tspan := otrace.FromContext(ctx)","sourceCodeStart":690,"sourceCodeEnd":726,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/edgraph/access.go#L690-L726","documentation":"In the ACL mutation/query authorization path (authorizePreds caller), a non-guardian user attempting a DropAll (or drop of all DATA) is rejected with this error. Drop-all is reserved for members of the guardians group.","triggerScenarios":"An authenticated non-guardian user issues an Alter with DropOp (DropAll or DropData) through /alter or the Alter RPC while ACLs are enabled.","commonSituations":"CI pipelines or scripts running drops with a regular user's JWT instead of the guardian (galaxy) token; forgotten JWT from a previous non-admin login; multi-tenant apps exposing drop to app users.","solutions":["Re-authenticate as a user in the 'guardians' group (galaxy) and retry the drop","Add the current user to the guardians group via the ACL API if they legitimately need drop rights","Issue a fresh JWT with a guardian identity (dgraph acl login or auth token endpoint)","Do the drop in a separate connection/session with admin credentials"],"exampleFix":"// before: dropping with non-guardian JWT\ndg.Alter(ctx, &api.Operation{DropOp: api.Operation_ALL})\n// after: login as guardian first\n// dgraph acl login -u gagali -p <password> -d <url>  -> obtain JWT for galaxy/guardian\ndg = newClientWithGuardianToken()\ndg.Alter(ctx, &api.Operation{DropOp: api.Operation_ALL})","handlingStrategy":"validation","validationCode":"// Confirm the JWT's user is in guardians before issuing a drop\nimport { JwtVerify } from 'jose'\nconst { payload } = await jwtVerify(token, key)\nconst groups = (payload['https://dgraph.io/jwt/claims'] ?? {}).groups ?? []\nif (!groups.includes('guardians')) {\n  throw new Error('current user cannot drop all data')\n}","typeGuard":"function isGuardian(claims) {\n  const groups = claims?.['https://dgraph.io/jwt/claims']?.groups\n  return Array.isArray(groups) && groups.includes('guardians')\n}","tryCatchPattern":"try {\n  await dg.alter({ dropOp: 'ALL' })\n} catch (e) {\n  if (/only guardians are allowed to drop/.test(e.message)) {\n    // re-login with a guardian (galaxy) JWT and retry once\n  }\n  throw e\n}","preventionTips":["Keep admin (drop) operations in a separate deployment with guardian credentials","Never expose DropAll endpoints to application users' tokens","Rotate/check which JWT your CI uses before destructive jobs"],"tags":["acl","permission","drop-all","authorization"],"backgroundTag":"insufficient-acl-permissions","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}