Description
[READ] Step 1: Are you in the right place?
I don't know, I think so. I'm filing a corresponding issue with GCP.
[REQUIRED] Step 2: Describe your environment
- Operating System version:
macOS 10.14.5
- Firebase Admin SDK version:
7.0.0
Library version: _____using the admin SDK- Firebase Product: Firestore
[REQUIRED] Step 3: Describe the problem
When using a value as a cursor in a collection group query, against the document name (__name__
), I get an INVALID_ARGUMENT
error in gRPC from Firestore. I'm not entirely sure if this is an issue with the request or the server, but the response would indicate it is a client-side issue (INVALID_ARGUMENT
roughly corresponds to HTTP 400
).
In our case, the document name matches the value we want to query for. We want to get the parent of these documents, so, we do a collection group query, using the value as the cursor, against the document name. Instead of working, though, it produces INVALID_ARGUMENT
as described above.
Steps to reproduce:
- Setup a Firestore database where you have an object that looks like this:
/someCollection/someDocumentOne
:
{
"something": "hi"
}
/someCollection/someDocumentOne/someSubcollection/someDocumentTwo
:
{
"something2": "hey",
"thingType": "something"
}
- Setup a Firebase project really quick, using the NodeJS toolchain. Make sure to enable Firebase and Functions.
> mkdir test && cd test
> firebase init
- Jump into your Firebase functions index, and add the following:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase)
let db = admin.firestore();
function resolveBySubCollection(subdocName) {
const mappedDocs = db.collectionGroup("someSubcollection");
const query = mappedDocs
.where("thingType", "=", "something")
.orderBy("__name__")
.startAt(subdocName)
.limit(1);
return query.get();
}
exports.findBySKU = functions.https.onRequest((request, response) => {
return resolveBySubCollection("someDocumentTwo").then(querySnapshot => {
querySnapshot.forEach(documentSnapshot => {
console.log("matched document: " + documentSnapshot.ref.path);
});
response.send("OK");
});
});
Relevant Code:
The particular code that we want to work, but is failing, is the following (grafted from above):
const query = mappedDocs
.where("thingType", "=", "something")
.orderBy("__name__")
.startAt(subdocName)
.limit(1);
Specifically, it seems to be the .startAt()/.orderBy()
on __name__
that is causing the error. The error encountered (in the local Firebase function emulator, and in production) is:
firebase > i Your code has been provided a "firebase-admin" instance.
⚠ Error: 3 INVALID_ARGUMENT: Resource name "projects/<project-id>/databases/(default)/documents/subCollectionTwo" lacks "/" at index 62.
at Object.exports.createStatusError (/Volumes/.../functions/node_modules/grpc/src/common.js:91:15)
at ClientReadableStream._emitStatusIfDone (/Volumes/.../functions/node_modules/grpc/src/client.js:233:26)
at ClientReadableStream._receiveStatus (/Volumes/.../functions/node_modules/grpc/src/client.js:211:8)
at Object.onReceiveStatus (/Volumes/.../functions/node_modules/grpc/src/client_interceptors.js:1272:15)
at InterceptingListener._callNext (/Volumes/.../functions/node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.onReceiveStatus (/Volumes/.../functions/node_modules/grpc/src/client_interceptors.js:618:8)
at /Volumes/.../functions/node_modules/grpc/src/client_interceptors.js:1029:24
⚠ Your function was killed because it raised an unhandled error.
RESPONSE RECEIVED FROM FUNCTION: 500, "Error: 3 INVALID_ARGUMENT: Resource name \"projects/<project-id>/databases/(default)/documents/someCollectionTwo\" lacks \"/\" at index 62.\n at Object.exports.createStatusError (/Volumes/.../functions/node_modules/grpc/src/common.js:91:15)\n at ClientReadableStream._emitStatusIfDone (/Volumes/.../functions/node_modules/grpc/src/client.js:233:26)\n at ClientReadableStream._receiveStatus (/Volumes/.../functions/node_modules/grpc/src/client.js:211:8)\n at Object.onReceiveStatus (/Volumes/.../functions/node_modules/grpc/src/client_interceptors.js:1272:15)\n at InterceptingListener._callNext (/Volumes/.../functions/node_modules/grpc/src/client_interceptors.js:568:42)\n at InterceptingListener.onReceiveStatus (/Volumes/.../functions/node_modules/grpc/src/client_interceptors.js:618:8)\n at /Volumes/.../functions/node_modules/grpc/src/client_interceptors.js:1029:24"