FR: [FB Messaging] Expose full FirebaseError
AustinHunt opened this issue · comments
[REQUIRED] Step 2: Describe your environment
- Operating System version: macOS
- Firebase SDK version: latest
- Library version: v4.12.0
- Firebase Product: messaging
[REQUIRED] Step 3: Describe the problem
Steps to reproduce:
The messaging api returns robust error codes to tell your application what went wrong with the server. This go-lang library abstracts this away and only gives you the following struct: https://github.com/firebase/firebase-admin-go/blob/v4.12.0/messaging/messaging_batch.go#L78
This makes it impossible to react to different kinds of failures when calling sendBatch
. In my case, I want to remove invalid device tokens from my database.
If the lib could return this struct (
firebase-admin-go/internal/errors.go
Line 87 in 74c9bd5
Relevant Code:
func (firebaseSender *FirebaseSender) cleanupDevices(ctx context.Context, batchResponse *messaging.BatchResponse) {
if batchResponse.FailureCount == 0 {
return
}
for _, sendResponse := range batchResponse.Responses {
logger.Debug(sendResponse.Error) // Expose ErrorCode here so that I can switch and deal with different kinds of failures.
}
}
The internal library has the data structure I need, but it is in the internal library and unavailable to other modules.
// ErrorCode represents the platform-wide error codes that can be raised by
// Admin SDK APIs.
type ErrorCode string
const (
// InvalidArgument is a OnePlatform error code.
InvalidArgument ErrorCode = "INVALID_ARGUMENT"
// FailedPrecondition is a OnePlatform error code.
FailedPrecondition ErrorCode = "FAILED_PRECONDITION"
// OutOfRange is a OnePlatform error code.
OutOfRange ErrorCode = "OUT_OF_RANGE"
// Unauthenticated is a OnePlatform error code.
Unauthenticated ErrorCode = "UNAUTHENTICATED"
// PermissionDenied is a OnePlatform error code.
PermissionDenied ErrorCode = "PERMISSION_DENIED"
// NotFound is a OnePlatform error code.
NotFound ErrorCode = "NOT_FOUND"
// Conflict is a custom error code that represents HTTP 409 responses.
//
// OnePlatform APIs typically respond with ABORTED or ALREADY_EXISTS explicitly. But a few
// old APIs send HTTP 409 Conflict without any additional details to distinguish between the two
// cases. For these we currently use this error code. As more APIs adopt OnePlatform conventions
// this will become less important.
Conflict ErrorCode = "CONFLICT"
// Aborted is a OnePlatform error code.
Aborted ErrorCode = "ABORTED"
// AlreadyExists is a OnePlatform error code.
AlreadyExists ErrorCode = "ALREADY_EXISTS"
// ResourceExhausted is a OnePlatform error code.
ResourceExhausted ErrorCode = "RESOURCE_EXHAUSTED"
// Cancelled is a OnePlatform error code.
Cancelled ErrorCode = "CANCELLED"
// DataLoss is a OnePlatform error code.
DataLoss ErrorCode = "DATA_LOSS"
// Unknown is a OnePlatform error code.
Unknown ErrorCode = "UNKNOWN"
// Internal is a OnePlatform error code.
Internal ErrorCode = "INTERNAL"
// Unavailable is a OnePlatform error code.
Unavailable ErrorCode = "UNAVAILABLE"
// DeadlineExceeded is a OnePlatform error code.
DeadlineExceeded ErrorCode = "DEADLINE_EXCEEDED"
)
// FirebaseError is an error type containing an error code string.
type FirebaseError struct {
ErrorCode ErrorCode
String string
Response *http.Response
Ext map[string]interface{}
}
func (fe *FirebaseError) Error() string {
return fe.String
}
I'm using Firebase Auth, when it fails to verify a token, Im able to know the reason from the message, however, because the ErrorCode and Ext fields are not exposed, I'm not able to handle each case programmaticlly.
So yep, it will be really helpful to expose the fields and error codes, please add the feature, thank you!
I also have troubles with the FirebaseError
being in an internal package, since there is no way to use it in e.g. errors.Is
or errors.As
(the idiomatic way to compare errors) as well as to create such an error on my own (e.g. in a mock used in unit tests), which makes it unnecessarily hard to test code using this module for interactions with Firebase. Since the FirebaseError
is returned from the methods provided by this module, I consider it as part of the API and therefore it should be exposed.
The errorutils
package is somewhat helpful, but to me, it looks more like a workaround.
@lahirumaramba I see you are most active maintainer so just wanted to ask if this is something you are considering to expose?
It would be extremely useful like others mentioned already.