Closed jstansbe closed 4 years ago
Hi @jstansbe. You're not doing anything wrong. We don't expose any additional error details in the SDK at the moment. There's just a simple FirebaseException
type that exposes a string, and this string may also include the full HTTP response text (which is what you're seeing).
There's a broader effort in progress to improve how errors are exposed in the SDK (it's being proposed across all of our SDKs). It's still at very early stages, and I don't have a concrete timeline for you. But when that effort lands, you will be able to easily check for error codes, and handle your errors accordingly.
The proposed API is something like:
class FirebaseException extends Exception {
ErrorCode Code;
String Message;
HttpResponseMessage? HttpResponse; // System.Net.Http.HttpResponseMessage
Exception InnerException;
}
class FirebaseMessagingException extends FirebaseException {
MessagingErrorCode? MessagingErrorCode;
}
Unfortunately this means at the moment, you have to split and parse the exception message yourself to get any meaningful information out of it.
I should also point out that the FCM errors codes in the documentation are only really supported in our Node.js SDK. None of the other SDKs ever supported them, and they will most likely go away completely when the new error handling proposal is implemented (or they will get absorbed to the new MessagingErrorCode
type mentioned above).
Thanks for the info regarding this @hiranya911. I'm looking forward to being able to handle error codes from the Admin SDK more easily in .NET!
HttpResponseMessage? HttpResponse; // System.Net.Http.HttpResponseMessage
Cool, my application can then get Retry-After from there, like the documentation of messaging/server-unavailable says it must do.
Unfortunately this means at the moment, you have to split and parse the exception message yourself to get any meaningful information out of it.
I think my application needs to search for the first newline, check that it is followed by "{", and parse JSON starting from there. I'd also like it to check that the HTTP response had Content-Type: application/json but it seems the library does not yet surface that information.
I should also point out that the FCM errors codes in the documentation are only really supported in our Node.js SDK.
I originally got the impression that those error codes would appear directly in the HTTP response. Can Google please clarify the documentation? I think keeping this issue open on GitHub may also help other users of the SDK figure the problem out faster.
Cool, my application can then get Retry-After from there, like the documentation of messaging/server-unavailable says it must do.
In the future the SDK will automatically handle retries. This is already implemented in our Java, Python and Go SDKs, and being currently implemented in Node.js (see https://github.com/firebase/firebase-admin-node/pull/518). C# SDK will also have the same feature eventually.
I think my application needs to search for the first newline, check that it is followed by "{", and parse JSON starting from there. I'd also like it to check that the HTTP response had Content-Type: application/json but it seems the library does not yet surface that information.
You don't have to do any of that. System.Net.Http.HttpResponseMessage
exposes the headers and content separately: https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpresponsemessage?view=netframework-4.8
I originally got the impression that those error codes would appear directly in the HTTP response.
The error codes currently in our documentation are not available on the actual HTTP responses. They are added by the SDKs. We are also working towards removing these SDK-specific error codes. Our new error handling regime will be aligned with https://cloud.google.com/apis/design/errors. These new errors codes will be present on the HTTP responses.
You don't have to do any of that.
I meant my application needs to search for a newline when it is still using FirebaseAdmin 1.4.0 or earlier.
Just ran into this issue as well. Having to parse JSON in an exception message is kind of ridiculous. The solution that @hiranya911 described sounds great, but I'm confused why at least the FirebaseMessagingException
from the Java SDK hasn't been added in the meantime.
Here's the finalized design for the new exception types:
namespace FirebaseAdmin
enum ErrorCode
InvalidArgument
FailedPrecondition
OutOfRange
Internal
… other error codes
class FirebaseException : Exception
ErrorCode ErrorCode { get; }
System.Net.Http.HttpResponseMessage HttpResponse { get; }
string Message { get; } // inherited
Exception InnerException { get; } // inherited
namespace FirebaseAdmin.Auth
enum AuthErrorCode
InvalidIdToken
ExpiredIdToken
TokenSignFailed
CertificateFetchFailed
UserNotFound
DuplicateLocalId
… other FirebaseAuth error codes
class FirebaseAuthException : FirebaseException
AuthErrorCode? AuthErrorCode
namespace FirebaseAdmin.Messaging
enum MessagingErrorCode
ThirdPartyAuthError
Unregistered
Internal
InvalidArgument
SenderIdMismatch
Unavailable
QuotaExceeded
class FirebaseMessagingException : FirebaseException
MessagingErrorCode? MessagingErrorCode
@hiranya911 Will the new exception structures be included in the next release of the SDK?
@swebgit They will be released incrementally over a series of releases.
Note that the FCM APIs now support the fine-grained error handling scheme outlined above. FirebaseMessagingException
and MessagingErrorCode
types were included in the v1.8 release. More to come.
@hiranya911 So if we get a MessagingErrorCode.InvalidArgument
, what is the recommended way to determine which argument was invalid? Is the only option still to parse the exception message as JSON?
A lot of the time, the error message indicates what went wrong.
FirebaseAdmin.Messaging.FirebaseMessagingException : The registration token is not a valid FCM registration token
This is directly extracted from the error response sent by FCM:
{
"error": {
"code": 400,
"message": "The registration token is not a valid FCM registration token",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
"errorCode": "INVALID_ARGUMENT"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "message.token",
"description": "The registration token is not a valid FCM registration token"
}
]
}
]
}
}
If a certain INVALID_ARGUMENT error message doesn't have enough details, let us know by filing an issue (please provide enough details for us to repro the behavior), and we can work with the FCM team to get the necessary details included in the FCM server response.
Also note that we don't expect the clients to "handle" this sort of errors at runtime. INVALID_ARGUMENT errors are (usually) client errors and therefore should be "fixed" by the developers as opposed to "handling". A typical course of action at runtime would be to log the error message and other useful information, so the problem can be easily debugged and fixed.
In a future release (most likely the next release), clients will also have direct access to the HttpResponse
object responsible for this type of errors, so they can dump all the relevant information (headers, payload etc).
Suppose a mobile app has sent a registration token to my server, which then tries to send FCM messages to the mobile app, but the token turns out to be invalid. In this case, I'd like my server to recognize the error so that it can stop trying to use the invalid token for any other messages. Should the server then recognize the "The registration token is not a valid FCM registration token" string in the exception? This won't be localized?
My use case is pretty much identical to @KalleOlaviNiemitalo's. Being able to recognize invalid tokens at runtime is pretty key, and I believe the response for invalid tokens is InvalidArgument
.
As shown in my previous comment, the FCM server response doesn't provide any more granular information in this case. But I do see the point of your use case. Perhaps it makes sense to introduce a new type.googleapis.com/google.firebase.fcm.v1.FcmError
error code to signal invalid FCM tokens (this should be done in the FCM server first).
Can I ask one of you to file a new issue describing this use case?
dead @hiranya911, In my .Net client I am using following method:
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
Add.2. I want be able to retry message only if there was some server errors - not business validation such as wrong device ID , etc.
There's no way to detect if a message was delivered to a client app or not. FCM is an asynchronous messaging system. You can only know if a message was successfully handed off to FCM or not (indicated by the return value or the exception raised by the SDK). Client device delivery depends on many factors, some of which are not under your or even Firebase's control (e.g. the target device may be down, or the user may have uninstall the app).
MessagingErrorCode.Unavailable
is the error code.
A lot of the time, the error message indicates what went wrong.
FirebaseAdmin.Messaging.FirebaseMessagingException : The registration token is not a valid FCM registration token
This is directly extracted from the error response sent by FCM:
{ "error": { "code": 400, "message": "The registration token is not a valid FCM registration token", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError", "errorCode": "INVALID_ARGUMENT" }, { "@type": "type.googleapis.com/google.rpc.BadRequest", "fieldViolations": [ { "field": "message.token", "description": "The registration token is not a valid FCM registration token" } ] } ] } }
If a certain INVALID_ARGUMENT error message doesn't have enough details, let us know by filing an issue (please provide enough details for us to repro the behavior), and we can work with the FCM team to get the necessary details included in the FCM server response.
Also note that we don't expect the clients to "handle" this sort of errors at runtime. INVALID_ARGUMENT errors are (usually) client errors and therefore should be "fixed" by the developers as opposed to "handling". A typical course of action at runtime would be to log the error message and other useful information, so the problem can be easily debugged and fixed.
In a future release (most likely the next release), clients will also have direct access to the
HttpResponse
object responsible for this type of errors, so they can dump all the relevant information (headers, payload etc).
I might have misunderstood something here but the response I get from FCM for the exact same error does not include the details
part of the response that you have in your example. Is there a specific configuration needed to get the detailed errors, or did you mean that the details
section will also be available in an upcoming release of FCM?
@mickeahlinder You need #107 for that. That's not yet released.
Yes, Thank you. After some further research I figured that out. I managed to set that header myself using a DelegatingHandler and managed to get the MessagingErrorCode populated on the FirebaseMessagingException, so it seems to be working, or am I just lucky? Is it brittle to use that header along with the 1.8.0 release?
@mickeahlinder Nice 👍 The SDK already has the correct parsing logic to handle the details section of the error response. So you're all set. You can remove your custom handler, when you upgrade to a newer version of the SDK in the future.
Cool, thanks for your swift replies. Much appreciated! 😀
@mickeahlinder how did you set up the Delegating Handler? looks like the code that adds the header which results in FirebaseMessagingException.MessagingErrorCode getting populated was added 7 days after 1.8.0 was published and no new packages have been published yet.
or
@hiranya911 could we get a 1.8.1 package published now that the request.Headers.Add("X-GOOG-API-FORMAT-VERSION", "2"); header is getting set?
This issue is completely addressed as of the v1.9.0 release.
what are the possible errors need to be handled to make it fault tolerant?
Hi - any suggestions what to do when it only says "message": "Internal error encountered." "errorCode": "INTERNAL"
Is that a problem within Firebase or a config problem It has been working OK upto now
I'm trying to determine when there is an invalid token, an expired token, message rate exceeded error, etc. (https://firebase.google.com/docs/cloud-messaging/send-message#admin_sdk_error_reference).
When i send a single message/notification to a token like so:
var response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
I get the following response (I'm getting this when i catch a thrown exception from FirebaseMessaging... I think i must be using this incorrectly as this seems strange... shouldn't there be a response object?).
What am I doing that is incorrect? Shouldn't I be able to find a code that matches to whats in the admin_sdk_error_reference section? (link i have above)