Realm Data Access Rules Error ( error validating rule: do not know how to expand '%%root')

New to Realm, trying to create a rule that states: “if the user ID of the account equals the “uid” field, OR if the document does not yet exist AND the uid argument is equal to the user ID, allow a write”. Not totally sure if the expressions I wrote correctly execute that rule, but I am getting an error:

error validating rule: do not know how to expand ‘%%root’

for the expressions:

 {
     "%or": [
         { "uid": "%%user.id" },
         {
           "%%root.status": "new",
           "%%args.body.uid": "%%user.id"
         }
     ]
}

root.status is a valid expansion according to the documentation, so I’m not sure what the issue is.

Hey Jeremy! Welcome to the forums :wave:

I think you’re on the right track for your rule definition but I definitely see some issues. One thing that would be very helpful to know - what are you writing this rule expression for? Is this the partition-level read/write rules for sync? Or is it collection-level roles on a non-synced cluster?

If you’re defining rules for a non-synced collection, see below. Based on your error though I don’t think this is the case.

If you’re defining sync rules, then %%root and other document-level expansions aren’t available because sync does not support document-level rules. Instead, you’ll want to design a partition strategy for your app and then define read/write rules for your partitions.


For a non-synced collection, I assume this is an Apply When expression for a role.

The first user id part looks correct to me! i.e. “if the user ID of the account equals the “uid” field”

{ "uid": "%%user.id" } // This part is good!

For the second part I think you’re confused about how %%root and %%args work. These are only available in some rule expressions depending on where you’re using them. Specifically -

  • %%root is only available in MongoDB rule expressions (i.e. the apply when for a role) and represents a changed (or inserted) document after the change has been applied. The properties on %%root are the same as in your document, so %%root.status only means something if the document you’re evaluating rules for has a status field. There’s also a %%prevRoot expansion that represents the document before the change is applied.

  • %%args is only available in third party service rules and represents the named arguments that you pass to a service action. For example, if I called twilio.send({ to: "+15558675309", from: "+15551234567", body: "Hello from Realm!" }); then %%args would let me access the values of from, to, and body in my rule.

I’m a little unsure what you’re referring to when you say “the uid argument” - what function are you calling with this argument where you expect the rule to run?

To represent “the document does not yet exist” you can use %%prevRoot like so:

{ "%%prevRoot": { "$exists": false } }

Hello, nice to meet you Nick.

May I ask, what is difference between by example query with %%root._id and just query by the field _id? I see virtually no difference between the two.