Analytics unknown exceptions
Description
On iOS, I'm starting to receive reports in Crashlytics regarding Analytics:
Fatal Exception: FlutterError
UnknownException { "message": "An unknown error occurred", "underlyingException": "Instance of 'GDb'" }
Fatal Exception: FlutterError
0 App EventClient._flushEvents + 223 (event_client.dart:223)
1 App EventClient._listenForFlushEvents + 62 (event_client.dart:62)
It seems the exceptions are thrown when the flushEvents function is triggered but I don't understand the meaning of the underlying exception Instance of 'GDb'. Maybe it's something the pinpoint team might know?
Another report I got is the same exception but instead of Instance of GDb I got Instance of 'CDb'
On Android, I'm getting other kinds of exceptions:
Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: UnknownException {
"message": "Unexpected end of input",
"underlyingException": "FormatException: Unexpected end of input (at character 1)\n\n^\n"
}
#00 (EventClient._flushEvents [event_client.dart:229])
#01 (EventClient._listenForFlushEvents [event_client.dart:62])
I'm getting those reports from multiple users and it seems that it's increasing.
Unfortunately, I didn't find a way to reproduce locally.
Categories
- [x] Analytics
- [ ] API (REST)
- [ ] API (GraphQL)
- [ ] Auth
- [ ] Authenticator
- [ ] DataStore
- [ ] Notifications (Push)
- [ ] Storage
Steps to Reproduce
N/A
Screenshots
No response
Platforms
- [x] iOS
- [x] Android
- [ ] Web
- [ ] macOS
- [ ] Windows
- [ ] Linux
Flutter Version
3.29.2
Amplify Flutter Version
2.6.1
Deployment Method
Amplify CLI (Gen 1)
Schema
Hello @jamilsaadeh97, I'm sorry you are experiencing this issue. We will try to reproduce on our side and get back to you with any updates.
Are you using any event names or global properties that could be using unusual ASCII characters?
Hi @tyllark , Event names are all written in plain English, but some of them I'm adding a string property based on the user input. Is there any known ASCII characters that might trigger this exception?
Hello @jamilsaadeh97, sorry for the delay but I've been unable to reproduce the issue. We don't have any known ASCII characters that could cause this issue, but your android error FormatException: Unexpected end of input (at character 1)\n\n^\n indicated a malformed string. Your stack trace indicates the exception is coming from the HTTP call to Pinpoint's PutEvents operation. Can you please check AWS Console -> CloudTrail -> Event history to see if Pinpoint is recording the errors there.
If you find a way to reproduce the issue locally we can get additional HTTP error details by updating your FlutterError.onError and PlatformDispatcher.instance.onError callbacks to include the following:
FlutterError.onError = (FlutterErrorDetails details) {
_printUnknownException(details.exception);
};
PlatformDispatcher.instance.onError = (Object error, StackTrace stack) {
_printUnknownException(error);
return true;
};
//Add smithy: ^0.7.4 to pubspec.yaml
void _printUnknownException(Object e) {
if (e is UnknownException) {
final underlyingException = e.underlyingException;
if (underlyingException is SmithyHttpException) {
safePrint('''
SmithyHttpException:
StatusCode=${underlyingException.statusCode},
Headers=${underlyingException.headers},
Message=${underlyingException.message},
UnderlyingException=${underlyingException.underlyingException},
''');
}
}
}
Hi @tyllark Thanks for the update. I will try to reproduce it locally and hopefully get the extra exception info.
Will keep you posted
Hello @jamilsaadeh97, have you had any luck reproducing this issue locally? If not we can close this issue and you can open a new one when you are able to reproduce the issue locally.
Hi @tyllark , I did not reproduce it locally but I'm still receiving the same reports from Crashlytics. Will go ahead and close this and will let you know once I have more information.
This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.
Hello @tyllark , I followed your suggestion and got the extra debugging info. However I sent them to you in Discord since they might contain sensitive info.
Hello @jamilsaadeh97, thank you for following up with the debug information!
The exception in the discord message is an SmithyHttpException with an x-amzn-errortype: InvalidSignatureException and no underlying exception. Most likely this is a 1 off exception where the user's credentials expired while we were calling Pinpoint. We cache analytic events locally and have retry logic in place, so unless you are experiencing this issue frequently or their are additional side effects it shouldn't be a problem.
This is different from the exception initially mentioned in this issue, which we would still need additional information to investigate:
UnknownException { "message": "An unknown error occurred", "underlyingException": "Instance of 'GDb'" }
Hi @tyllark It is happening frequently and even on an app that does not use the record event API manually (just the automatically recorded events: session start and end).
As for the original exception, Instance of 'GDb' , it is the same but I discovered that "GDb" in this instance is the obfuscated class name. This means that the underlying dart sdk, generated by smithy, uses class.runtimeType, which will cause class names to be obfuscated when reported to crashlytics
It is mentioned as a caveat in the flutter obfuscation docs with an example:
https://docs.flutter.dev/deployment/obfuscate#caveat
And this article for more info:
https://medium.com/@tomastisocco97/the-risks-of-using-runtimetype-tostring-method-in-obfuscated-flutter-code-8024e4f7d5ae
So I guess there are two issues here:
- The signature exception triggering frequently.
- The obfuscation of underlying class runtime types
Hello @jamilsaadeh97, thank you for the additional clarification. Since the exception/underlyingException chain seems to be UnknownException -> SmithyHttpException (aka GDb when obfuscated) -> null I will attempt to reproduce the issue locally by creating a script that triggers event flushes as my access token expires.