I'm building a react-native app using Create React Native App. For the backend it uses Firebase Firestore. The app works fine on iOS but fails with the following error on Android (both with simulator and on a device) when trying to fetch data from the backend:
22:02:37: [2018-05-22T05:02:33.751Z] #firebase/firestore:, Firestore (4.10.1): Could not reach Firestore backend.
- node_modules\react-native\Libraries\ReactNative\YellowBox.js:71:16 in error
- node_modules\#firebase\logger\dist\cjs\src\logger.js:97:25 in defaultLogHandler
- ... 18 more stack frames from framework internals
Any idea what can be the problem and how to debug this?
The error seems to be a generic, as there are other questions with the same error message. But in this case it's specific to Android only.
Full log and the stack trace:
21:50:51: Warning: Expo version in package.json does not match sdkVersion in manifest.
21:50:51:
21:50:51: If there is an issue running your project, please run `npm install` in C:\Users\grigor\Documents\Bitbucket\AwesomeProject and restart.
21:51:08: Finished building JavaScript bundle in 26098ms
21:51:14: Running app on XT1053 in development mode
21:51:34: [2018-05-25T04:51:26.597Z] #firebase/firestore:, Firestore (4.10.1): Could not reach Firestore backend.
- node_modules\react-native\Libraries\ReactNative\YellowBox.js:71:16 in error
- node_modules\#firebase\logger\dist\cjs\src\logger.js:97:25 in defaultLogHandler
- ... 18 more stack frames from framework internals
21:51:37: Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See https://github.com/facebook/react-native/issues/12981 for more info.
(Saw setTimeout with duration 3299464ms)
- node_modules\react-native\Libraries\ReactNative\YellowBox.js:82:15 in warn
- node_modules\react-native\Libraries\Core\Timers\JSTimers.js:254:8 in setTimeout
- node_modules\#firebase\auth\dist\auth.js:37:577 in Hc
* null:null in <unknown>
- node_modules\#firebase\auth\dist\auth.js:15:932 in y
- node_modules\#firebase\auth\dist\auth.js:37:606 in Ic
- node_modules\#firebase\auth\dist\auth.js:210:0 in kk
- node_modules\#firebase\auth\dist\auth.js:209:665 in start
- node_modules\#firebase\auth\dist\auth.js:215:38 in Dk
- node_modules\#firebase\auth\dist\auth.js:253:425 in ql
- node_modules\#firebase\auth\dist\auth.js:255:146 in <unknown>
- node_modules\#firebase\auth\dist\auth.js:19:220 in <unknown>
* null:null in Gb
* null:null in Cb
- node_modules\#firebase\auth\dist\auth.js:22:103 in Sb
- node_modules\#firebase\auth\dist\auth.js:15:643 in jb
- ... 10 more stack frames from framework internals
I don't have an exact solution for the problem, but I realised that the way in which I was interacting with firebase made my application more susceptible. Maybe you can spot some of my own design flaws in your project?
What I've found is that I was calling initializeApp outside of a try/catch, which meant that the entire JavaScript module would fail whenever the error is encountered. So, the first work around is to properly handle initialization safely.
Secondly, this error became prominent in the way in which I structured my my calls to firestore(). For example, my first call to firebase.firestore() was embedded within a method that returned a Promise, i.e.:
() => firebase.firestore().collection('someCollection').get().then(...).catch(e => ...);
Now, with this approach, if the interaction with firestore failed before a Promise could be returned, we don't actually catch the error! This is because it occurs too early in the chain for a Promise to be created. This meant that again, the application would appear to fail at apparently some much deeper level than something that could be caught inside the application. But that's wrong!
The correct implementation would be to wrap the interaction with firebase.firestore() within a Promise first:
return new Promise(resolve => firebase.firestore().collection(...)).then(q => ...).catch(e =>...);
Hope this helps in some way. I know it's a tricky problem!
Related
I have read dozens of articles and posts regarding this Uncaught Error: [$rootScope:inprog] $digest already in progress and have applied multiple fixes trying to prevent it but nothing has worked so far.
My app catches all errors and notifies my back end server of the error. Every time the above error happens it is immediately followed by another error: Uncaught TypeError: appVersion.replaceAll is not a function. appVersion is a global variable set earlier (app version example: 0.40.41)
dataObj[0].fullVer = appVersion.replaceAll(".","") ;
Investigating the replaceAll error I discovered that that function wasn't introduced until 2021 and thereby isn't necessarily supported on older browsers and is supported on Node 15+.
My app is running on Ionic v1 using Node: 14.17.5 and every time this double error triggers, its always happening on older Android versions, the most current version it happens on is Android 9.1...but often the errors are on Android 6 through 9.1 and appear to be on the same type of devices. So the replaceAll error makes sense....older Android (browser) versions on an app running sub Node 15.
To address the replaceAll error I am changing that code to:
dataObj[0].fullVer = appVersion.replace(/\./g, '');
Furthermore, the double error always seems to be triggering on Androids automated new (version) app testing. Every time the error happens its on a handful of the same device/model types running Android 6 - 9.1...but all of the devices have the identical device UUID - which tells me this is some script deploying virtual devices testing my app. Thus far, the errors have not happened on a real device with a real user. But that is just luck at this point.
Back to the $digest error, the stack trace is meaningless and provides me no data as to where or what is triggering it. I have replaced all $apply to $applyAsync and added $timeout to any watch i am using. There are too many in use to post code here. But the reported error is the following:
ErrorIn = http://localhost/lib/ionic/js/ionic.bundle.js
ErrorAt = 30511 : 13
Message = Uncaught Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.5.3/$rootScope/inprog?p0=%24digest
This is all quite ambiguous and I know my ask here isn't going to be easy to answer. But I am hoping that someone is able to think outside the box and point me in a new direction. What other methods can I use to track where/what is the root cause of this $digest error?
UPDATE:
My original post said the $digest error would then trigger the replaceAll error, but this is backwards. The replaceAll error is happening first and might be whats causing the $digest error. The timestamps on the the double errors shows the replaceAll error is happening about a half second before the $digest error.
I am hoping my replaceAll fix above will address all this...if it doesn't trigger then hopefully the $digest error will no longer trigger too. But why would the replaceAll trigger a $digest error at all?
I have build a plugin which performs machine learning tasks on an image and this takes up to a minute (or event more). During this time when the plugin is working, the flutter UI freezes and the OS shows an error asking whether we should wait or just kill the app.
I got 2 problems:
Flutter UI hangs even though the plugin is of course async
The plugin doesn't allow delayed result e.g. from a coroutine (I get this error: E/DartMessenger(15585): java.lang.IllegalStateException: Reply already submitted)
You can use Isolates, as quoted from this medium article on isolates:
If you have a computation to perform that’s so enormous it could
cause you to drop frames if it were run in the main isolate, then you
can use Isolate.spawn() or Flutter’s compute() function.
more info:
https://flutter.dev/docs/development/packages-and-plugins/background-processes
https://youtu.be/vl_AaCgudcY
I would like to debug a system framework running on an Android device.
In particular, GpsLocationProvider sometimes stops for a while, and I would like to know what it is doing. I found the class contains a android.os.Handler that gets messages posted to it, to communicate between threads. Sometimes it takes minutes between a message is sent, and Handler.handleMessage is called. I interpret that the thread belonging to the Handler's Looper is busy.
I would like to attach a debugger, pause that thread, and see what's currently executing. Alternatively, somehow get a traceback of that thread. Is there any way to do that?
I tried creating an Android Studio project from the source tree with development/tools/idegen/idegen.sh, but I'm not sure how to proceed from there. In case it matters, the (legacy) device is running Android 6.
I've also just discovered debuggerd. I call logcat -s GpsLocationProvider to find the corresponding PID, and feed it to debuggerd, both with and without -b argument. However, this only gives be a backtrace into native code. I don't see any java code there.
If I'm not mistaken, if you have the respective Android API version in your AndroidStudio (installed through SDK Manager), you can install debug variant of your app on the device and then put breakpoints inside Android's code.
This way you can pause the execution of the component's code and see what it's doing.
I'm having a big performance problem when using AWS Lambda.
I created some basic lambdas that connect to RDS MySQL database and insert/select/delete data in order to return it to the user.
In my client which is an Android App I'm invoking the lambda using aws-android-sdk-lambda:2.2.17 library.
The mismatch is that in the CloudWatch I'm seeing that the Lambdas are being performed really quick - around 60 ms but in my Android app I'm getting the results only after 8-12 seconds.
Unfortunately all that happen after Lambda finishes its invocation and user gets his response is a black box. The problem might be in the implementation of the AWS SDK but I doubt it.
Note - the internet connection is not the problem and it's not a cold execution problem.
Please advice
My Android app uses the AWS Java SDK for uploading user photos to S3.
Whenever a user's phone's clock is 'skewed', this causes all transfers to fail. This is a well documented aspect of S3:
http://aws.amazon.com/articles/1109?_encoding=UTF8&jiveRedirect=1#04
It appears that the upstream S3 service reports this error quite clearly:
HTTP Status Code: 403 Forbidden
Error Code: RequestTimeToo-Skewed
Description: The difference between the request time and the server's
time is too large.
However when using the Java SDK, it seems as if the informative 403 code is lost ... and I have only an opaque "TransferState.Failed" to go by (which incidentally is the same error if internet connectivity is lost, if it times out, etc...).
As far as I can tell from the docs:
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/index.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferProgress.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Transfer.TransferState.html
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Upload.html
There is no way to get the additional "RequestTimeToo-Skewed" metadata about a transfer failure.
Am I missing it? Is there any way to get additional error information when an S3 transfer fails using Amazon's Java SDK?
UPDATE #1:
A commenter kindly highlighted that I should clarity two points:
I am actually using the AWS SDK for Android (which seems very similar to the Java SDK, but is nonetheless distinct)
I am using the TransferManager class to perform my upload. Apparently, this is a high-level class that wraps the lower-level AmazonS3Client ... and this lower-level class should expose the error reporting I need, but I am still investigating the exact tradeoffs involved between TransferManager and AmazonS3Client. As far as I can tell, there is no way to get progress information via the (synchronous) AmazonS3Client.putObjectRequest which would be a blocker for me...
UPDATE #2:
My sincere thanks to Jason (of the AWS SDK team) for stopping by and helping me out here. The important information is, indeed, available as properties on an AmazonS3Exception if you use certain methods. The docs had originally confused me and I thought that a manual Thread.sleep() loop was required to poll status (and thus I could not leverage waitForCompletion or waitForException), but if you use ProgressListener on PutObjectRequest you can get full progress callbacks and the error-fidelity of AmazonS3Exception.
these two methods should help you out:
Transfer.waitForCompletion()
Transfer.waitForException()
If you detect that your transfer has failed based on a transfer progress event, you can simply call Transfer.waitForException() to be returned the exception that occurred. That exception will be an AmazonServiceException in this case, with all of the info that you need to see that the real problem was a clock skew issue.
Alternatively, the Transfer.waitForCompletion() method will unwrap the original exception from an ExecutionException and directly throw the original exception, just as if it'd all been happening on one thread. This might be a more convenient approach if you want to use a catch blocks to catch different types of errors cleanly and elegantly.
I disagree that the "catch Exception" block is "brutally broad". The point of that code is to catch any error that happens, mark the transfer as failed and rethrow the error so that the application code can know about it. If it were less broad, then that's exactly the case where exceptions could sneak through and transfer progress wouldn't be updated correctly and would be out of sync with reality.
Give those two methods and shot and let us know if that helps!
Well, I have debugged Amazon's SDK and I'm sorry to say that this information is being swallowed internally. Perhaps I will try to submit a patch.
Details: an AmazonS3Exception is being thrown internally which does in fact accurately report this exact error scenario, but a brutally broad try catch ( Exception e ) consumes it and washes away the specificity.
Here is the guilty try-catch:
https://github.com/aws/aws-sdk-java/blob/master/src/main/java/com/amazonaws/services/s3/transfer/internal/UploadMonitor.java#L145
Here is a screenshot showing that an AmazonS3Exception is correctly thrown with the right info...