Mr. Robot
Mr. Robot

Reputation: 1824

Firebase Cloud Functions: "status":"INVALID_ARGUMENT"

I am locally testing a Firebase Cloud Function. When I call this function using the local URL http://localhost:5001/projectName/us-central1/functionName as described here:

exports.createSession = functions.https.onRequest((_req, res) => {
  res.status(200).send('TESTING');
});

the function works and it returns the string.

However, when I call this function:

exports.createSession = functions.https.onCall((data, context) => {
  return 'TESTING';
});

It throws the error: {"error":{"message":"Bad Request","status":"INVALID_ARGUMENT"}}

I'd like to use the latter function because I want to access the context.auth object to check for user Firebase authentication.

I'm using Firebase CLI v8.4 and Node v10.20.

What am I missing from the second function to get it working? I am not calling it with any arguments as I do not need to.

Upvotes: 3

Views: 5605

Answers (3)

Sardar
Sardar

Reputation: 221

The accepted answer is pretty much complete just wanted to add an example for flutter users. You receive INVALID ARGUMENTS with 400 whenever you try to call firebase onRequest function with clientSDK's onCall methods you need to use fetch,axios etc to call onRequest function.

Flutter Example 🚫 :

static Future<void> registerViaPhone(
 String token) async {
 final HttpsCallable callable = 
FirebaseFunctions.instance.httpsCallable(
'registerViaPhone',
 );
try {
final result = await callable.call({
  'token': token,
});
print('result' + result.toString());
} catch (e) {
print('Error calling function: $e');
 }
}

Flutter Example ✅ :

static Future<void> registerViaPhone(String token) async {
const functionUrl=https://<region>-<project-id>.cloudfunctions.net/func;
try {
final response = await http.post(
   Uri.parse(functionUrl),
   headers: <String, String>{
     'Content-Type': 'application/json; charset=UTF-8',
   },
   body: jsonEncode(<String, String>{
     'token': token,
   }),
 );
 if (response.statusCode == 200) {
   // do something      } 
  } catch (error) {
  print('Error: $error');
 }
}

Upvotes: 0

Mr. Robot
Mr. Robot

Reputation: 1824

The answer is that you can't call the .onCall method in the same way as you can the onRequest method, you have to call it from the SDK. If the data argument is missing it will throw an error:

If the client trigger is invoked, but the request is in the wrong format, such as not being JSON, having invalid fields, or missing the data field, the request is rejected with 400 Bad Request, with an error code of INVALID_ARGUMENT.

So you have to call it with an argument even if you don't need to use the argument for anything.

Upvotes: 5

Doug Stevenson
Doug Stevenson

Reputation: 317467

You're comparing a callable function using onCall to an HTTP function using onRequest. Callable functions are implemented very differently than HTTP functions. I suggest reading over the documentation I linked in order to better understand the difference. The main point is that callable functions follow a specific protocol, and that any client access must follow that protocol, or possibly receive the error that you show here. The best implementation of that protocol is the client SDK provided by Firebase - you should use that to invoke the function.

If you want a normal HTTP function to be invoked using the usual HTTP libraries, then don't use a callable at all. You can pass authentication information to an HTTP function manually using an ID token then verify it using the Firebase Admin SDK. The documentation link has examples.

Upvotes: 5

Related Questions