So we're running into this really weird, seemingly random crash in the Parse SDK for Android. Normally we would attribute this to maybe a bug in the Parse platform, but it's happening pretty consistently to all our users, and researching the issue doesn't bring up any known causes. In fact, there is only one issue that mildly related to this one, which can be found here; link.
The basic breakdown is that we are detecting the following crash in our Crashlytics logs:
Fatal Exception: java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:787)
at java.util.HashMap$KeyIterator.next(HashMap.java:814)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:960)
at com.parse.ParseTraverser.visit(ParseTraverser.java:100)
at com.parse.ParseTraverser.visit(ParseTraverser.java:94)
at com.parse.ParseTraverser.visit(ParseTraverser.java:101)
at com.parse.ParseTraverser.visit(ParseTraverser.java:94)
at com.parse.ParseTraverser.visit(ParseTraverser.java:101)
at com.parse.ParseTraverser.traverse(ParseTraverser.java:137)
at com.parse.OfflineStore.saveLocallyAsync(OfflineStore.java:776)
at com.parse.OfflineStore.access$200(OfflineStore.java:36)
at com.parse.OfflineStore$38.then(OfflineStore.java:1251)
at com.parse.OfflineStore$38.then(OfflineStore.java:1227)
at bolts.Task$15.run(Task.java:917)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeAfterTask(Task.java:908)
at bolts.Task.continueWithTask(Task.java:715)
at bolts.Task.continueWithTask(Task.java:726)
at bolts.Task$13.then(Task.java:818)
at bolts.Task$13.then(Task.java:806)
at bolts.Task$15.run(Task.java:917)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeAfterTask(Task.java:908)
at bolts.Task.access$100(Task.java:32)
at bolts.Task$11.then(Task.java:708)
at bolts.Task$11.then(Task.java:705)
at bolts.Task.runContinuations(Task.java:956)
at bolts.Task.trySetResult(Task.java:994)
at bolts.TaskCompletionSource.trySetResult(TaskCompletionSource.java:39)
at bolts.TaskCompletionSource.setResult(TaskCompletionSource.java:62)
at bolts.Task$15$1.then(Task.java:934)
at bolts.Task$15$1.then(Task.java:921)
at bolts.Task$14.run(Task.java:872)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeImmediately(Task.java:863)
at bolts.Task.continueWith(Task.java:661)
at bolts.Task.continueWith(Task.java:672)
at bolts.Task$15.run(Task.java:921)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeAfterTask(Task.java:908)
at bolts.Task.access$100(Task.java:32)
at bolts.Task$11.then(Task.java:708)
at bolts.Task$11.then(Task.java:705)
at bolts.Task.runContinuations(Task.java:956)
at bolts.Task.trySetResult(Task.java:994)
at bolts.TaskCompletionSource.trySetResult(TaskCompletionSource.java:39)
at bolts.TaskCompletionSource.setResult(TaskCompletionSource.java:62)
at bolts.Task$15$1.then(Task.java:934)
at bolts.Task$15$1.then(Task.java:921)
at bolts.Task$14.run(Task.java:872)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeImmediately(Task.java:863)
at bolts.Task.continueWith(Task.java:661)
at bolts.Task.continueWith(Task.java:672)
at bolts.Task$15.run(Task.java:921)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeAfterTask(Task.java:908)
at bolts.Task.access$100(Task.java:32)
at bolts.Task$11.then(Task.java:708)
at bolts.Task$11.then(Task.java:705)
at bolts.Task.runContinuations(Task.java:956)
at bolts.Task.trySetResult(Task.java:994)
at bolts.TaskCompletionSource.trySetResult(TaskCompletionSource.java:39)
at bolts.TaskCompletionSource.setResult(TaskCompletionSource.java:62)
at bolts.Task$15$1.then(Task.java:934)
at bolts.Task$15$1.then(Task.java:921)
at bolts.Task$14.run(Task.java:872)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeImmediately(Task.java:863)
at bolts.Task.continueWith(Task.java:661)
at bolts.Task.continueWith(Task.java:672)
at bolts.Task$15.run(Task.java:921)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeAfterTask(Task.java:908)
at bolts.Task.access$100(Task.java:32)
at bolts.Task$11.then(Task.java:708)
at bolts.Task$11.then(Task.java:705)
at bolts.Task.runContinuations(Task.java:956)
at bolts.Task.trySetResult(Task.java:994)
at bolts.TaskCompletionSource.trySetResult(TaskCompletionSource.java:39)
at bolts.TaskCompletionSource.setResult(TaskCompletionSource.java:62)
at bolts.Task$15$1.then(Task.java:934)
at bolts.Task$15$1.then(Task.java:921)
at bolts.Task$14.run(Task.java:872)
at bolts.BoltsExecutors$ImmediateExecutor.execute(BoltsExecutors.java:105)
at bolts.Task.completeImmediately(Task.java:863)
at bolts.Task.continueWith(Task.java:661)
at bolts.Task.continueWith(Task.java:672)
at bolts.Task$15.run(Task.java:921)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Now as you can see this stacktrace doesn't show us where the issue is occurring in our code, and we are not able to reproduce it consistently. It appears to pop up randomly, opposed to the previous issue I linked.
Does anyone have any experience with this issue? If so, what is causing this? I've checked if our code somewhere loops trough a list of ParseObject
s and removes entries, but I can't find any instances of this happening.