firebase-tools: 8.16.2
Platform: macOS
Following the docs, I tried to debug the path
When I'm using the emulator _locally_, the path is like /databases/$(database)/documents/col1/doc1/col2/doc2/col3/doc3...
so this resource['__name__'][0] will be databases
and resource['__name__'][4] will be doc1
for example, this test function will return true _(locally, using the emulator)_:
function test() {
return string(resource['__name__'][4]).matches('doc1');
}
Or:
function test() {
return string(resource['__name__'][0]).matches('databases');
}
But, when I deploy the rules, the test function becomes false
Is it because the path in production is different? If so, how can I see it? is there any example for a production path..
UPDATE:
I tried the Rules Playground in Firebase Console and noticed that test function is true only if it's used for the first or second sub-collection, but it becomes false when it's used for the third sub-collection (e.g. col3) and throws this error:
Error running simulation — Error: simulator.rules line [xx], column [xx]. Null value error.
the error seems to be pointing at resource['__name__']
In the emulator, test function is always true no matter where it's used
When it's deployed, test function becomes false if it's used for a 3rd sub-collection.
full example:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /cols1/{col1} {
allow read, write: if true;
match /cols2/{col2} {
allow read, write: if test(); // this is true
function test() {
return string(resource['__name__'][0]).matches('databases');
}
match /cols3/{col3} {
allow read, write: if test(); // this is false
function test() {
return string(resource['__name__'][0]).matches('databases');
}
}
}
}
}
}
Expected the path to be the same in the emulator and production
Seems there's a different in the path between the emulator and production
This issue does not have all the information required by the template. Looks like you forgot to fill out some sections. Please update the issue with more information.
@google-oss-bot updated
@adotnusiyan thank you for the detailed report!
@yuchenshi can you assign this to someone who knows enough about the emulated rules engine to look into it?
@adotnusiyan Could you please try this against the Rules Playground in Firebase Console too? Once you test it against a mock request, you should also be able to inspect the results of the expression in the right panel.
@yuchenshi test function is false in the Rules Playground in Firebase Console which should be true
@yuchenshi @samtstern I updated the issue for full details. Thanks
I believe you're experiencing the error because resource variable is null in production in the request you're testing. Remember in rules that the resource variable is only available if the document already exists in the database -- e.g. for a get request, resource will be null unless the document cols1/doc1/cols2/doc2/cols3/doc3 exists in your database. You may have this already in your emulator but not in the production database.
Since you only need the path of the document, I'd suggest you use request.path instead. That variable is ALWAYS available and works just like resource['__name__']. For example, string(request.path[0]) gives you database.
Also, FYI, you can use the right panel to the detailed sub-expressions in the Rules Playground. For example, the following screenshot shows the value returned by the string(...) call.

@yuchenshi do I need to create a new issue for resource['__name__'] being null if it's used in the 3rd sub-collection in production only?
@adotnusiyan I did try your example in Firebase Console in the Rules Playground and I tested against all three levels. I found that if cols1/doc1/cols2/doc2/cols3/doc3 does not exist, then the function will throw a null value error. Once I create it in the Data tab in console, running the simulation again gives me true. This is consistent with top and second levels.
I don't want to jump into conclusions, but please make sure to double check the spelling of the paths in the Playground and Data tab to make sure they match exactly. If the issue persists, the best way for us to move forward is for you to create a minimal repro (e.g. a GitHub repository with sample rules and a script that reads data from the 3rd collection, on web or Node.js client (not admin)). Since there is nothing to be done in the Firebase CLI or Emulator Suite, I've also closed this issue -- production issues are better handled by Firebase Support.
Most helpful comment
I believe you're experiencing the error because
resourcevariable isnullin production in the request you're testing. Remember in rules that theresourcevariable is only available if the document already exists in the database -- e.g. for agetrequest,resourcewill be null unless the documentcols1/doc1/cols2/doc2/cols3/doc3exists in your database. You may have this already in your emulator but not in the production database.Since you only need the path of the document, I'd suggest you use
request.pathinstead. That variable is ALWAYS available and works just likeresource['__name__']. For example,string(request.path[0])gives youdatabase.Also, FYI, you can use the right panel to the detailed sub-expressions in the Rules Playground. For example, the following screenshot shows the value returned by the
string(...)call.