Uncaught exception in Firebase runloop (3.0.0)
Asked Answered
B

8

24

I'm using the latest firebase(9.0.2): build.gradle:

dependencies {
     ...
     compile "com.google.firebase:firebase-database:9.0.2"
     compile 'com.google.firebase:firebase-auth:9.0.2'
}
apply plugin: 'com.google.gms.google-services'

Project build.gradle

classpath 'com.google.gms:google-services:3.0.0'

And after some time application starts crashing with this Exception:

  Fatal Exception: java.lang.RuntimeException: Uncaught exception in Firebase runloop (3.0.0). Please report to [email protected]
       at com.google.android.gms.internal.zzadp$1$1.run(Unknown Source)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:135)
       at android.app.ActivityThread.main(ActivityThread.java:5274)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
Caused by java.lang.AssertionError: hardAssert failed: 
       at com.google.android.gms.internal.zzaiv.zzb(Unknown Source)
       at com.google.android.gms.internal.zzaiv.zzaN(Unknown Source)
       at com.google.android.gms.internal.zzagh.zzb(Unknown Source)
       at com.google.android.gms.internal.zzagh.<init>(Unknown Source)
       at com.google.android.gms.internal.zzaga.<init>(Unknown Source)
       at com.google.android.gms.internal.zzaga.<init>(Unknown Source)
       at com.google.android.gms.internal.zzadp.zza(Unknown Source)
       at com.google.android.gms.internal.zzaeu.zzic(Unknown Source)
       at com.google.android.gms.internal.zzafc.zzRy(Unknown Source)
       at com.google.android.gms.internal.zzafc.zza(Unknown Source)
       at com.google.android.gms.internal.zzafc$1.run(Unknown Source)
       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
       at java.util.concurrent.FutureTask.run(FutureTask.java:237)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
       at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
       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)

in onCreate of Application I have:

@Override
    public void onCreate() {
    ...
    FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}

and also we created singleton helper class for Firebase what called from Activities(all activities in the same process)/Fragments:

 private FirebaseHelper() {
        mFirebaseRef = FirebaseDatabase.getInstance().getReference();
        mFirebaseAuth = FirebaseAuth.getInstance();
        mFirebaseAuth.addAuthStateListener(this);
        authentication();
    }

    public static synchronized FirebaseHelper getInstance() {
        if (mInstance == null || mInstance.getFirebaseRef() == null) {
            mInstance = new FirebaseHelper();
        }
        return mInstance;
    }

Libraries:

dependencies {
    testCompile 'junit:junit:4.12'
    compile('com.crashlytics.sdk.android:crashlytics:2.5.6@aar') {
        transitive = true;
    }
    compile 'com.google.code.gson:gson:2.6.2'
    compile 'com.android.support:support-v4:23.4.0'
    compile 'com.android.support:support-v13:23.4.0'
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:design:23.4.0'
    compile 'com.android.support:support-annotations:23.4.0'
    compile 'com.android.support:gridlayout-v7:23.4.0'
    compile 'com.google.android.gms:play-services-base:9.0.2'
    compile 'com.google.android.gms:play-services-maps:9.0.2'
    compile 'com.google.android.gms:play-services-location:9.0.2'
    compile 'com.google.android.gms:play-services-appindexing:9.0.2'
    compile 'com.google.android.gms:play-services-analytics:9.0.2'
    compile 'com.google.firebase:firebase-messaging:9.0.2'
    compile 'com.facebook.android:facebook-android-sdk:4.11.0'
    compile 'de.greenrobot:eventbus:2.4.0'
    compile 'com.amazonaws:aws-android-sdk-core:2.2.12'
    compile 'com.amazonaws:aws-android-sdk-cognito:2.2.12'
    compile 'com.amazonaws:aws-android-sdk-s3:2.2.12'
    compile 'com.android.support:multidex:1.0.1'
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    compile 'com.squareup.retrofit2:converter-gson:2.0.2'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
    compile 'io.reactivex:rxandroid:1.2.0'
    compile 'io.reactivex:rxjava:1.1.5'
    compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
    compile 'com.github.curioustechizen.android-ago:library:1.3.0'
    compile 'com.cedarsoftware:json-io:4.4.0'
    compile 'com.timehop.stickyheadersrecyclerview:library:0.4.3@aar'
    compile 'joda-time:joda-time:2.9.3'
    compile 'com.facebook.fresco:fresco:0.10.0'
    compile 'com.facebook.fresco:imagepipeline-okhttp3:0.10.0'
    compile 'com.google.firebase:firebase-core:9.0.2'
    compile 'com.google.firebase:firebase-invites:9.0.2'
    compile 'com.google.firebase:firebase-database:9.0.1'
    compile 'com.google.firebase:firebase-auth:9.0.1'
    compile 'com.github.jd-alexander:LikeButton:0.2.0'

    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
    androidTestCompile 'junit:junit:4.12'
    androidTestCompile 'com.android.support:support-annotations:23.4.0'
    androidTestCompile 'com.android.support.test:runner:0.5'
    androidTestCompile 'com.android.support.test:rules:0.5'
    compile files('libs/core-3.2.1.jar')
}
Babbling answered 9/6, 2016 at 11:32 Comment(17)
@pRaNaY java.lang.StringIndexOutOfBoundsException: and java.lang.AssertionError: hardAssert failed: are the same ?Babbling
Thanks .My mistake , But the error which you got ,it is a child exception of Uncaught exception in Firebase runloop (3.0.0) so,I put flag for duplicate.Nicholasnichole
@Nicholasnichole I'm using the latest firebase library, I don't think that this question relatedBabbling
Also posted on groups.google.com/forum/#!topic/firebase-talk/iy0762S3KsU. We're looking into it.Screening
There is an issue with the database where multi-process and persistence can lead to crashes. Make sure you are not using multiple processes (note that processes can also be created by other libraries, for example crash reporting). Additionally check that if that is the case you are not using the database from the Application class as there might be multiple instances of Application with different processes.Galantine
@FrankvanPuffelen After remove FirebaseDatabase.getInstance().setPersistenceEnabled(true) application stoped crashing, but we don't have offline mode support now.Babbling
Thanks, that definitely helps. Can you show the code of how you initialize your Firebase app/database? It helps if we know how and where you initialize it.Screening
@FrankvanPuffelen I updated questionBabbling
I got same error after application have any crashes. I think crash make disruption to firebase offline persistence data.Rabinowitz
Hi @FrankvanPuffelen, any updates ?Babbling
Jonny asked a few questions too. Are you using multiple processes (keep in mind that those may come from other libraries that you use, e.g. many crash reporting libraries spawn a secondary process to transmit their crash reports)? And where do you call the initialization code from?Screening
@FrankvanPuffelen I added libraries what I'm using. I already tried to remove libraries like crashlytics, leakcanary. but it doesn't help.Babbling
@FrankvanPuffelen I'm called from Fragments/Activities onlyBabbling
@IgorB once the client reaches this state, removing libraries will not help anymore. So can you clarify if the client reaches this state after you removed the other libraries?Galantine
Please also take a look at my reply on the google group thread here: groups.google.com/forum/… And reply on that thread or to me directly ([email protected]) if you can provide more details or (ideally) a way to reproduce it.Hhour
related question: #38209378Kevel
Hi @FrankvanPuffelen any updates ?Babbling
E
9

We are facing the same issue on version 9.0.2 and 9.2.0. After many hours of investigation, we found that one way to reproduce this issue is to have a query with fixed endAt and startAt parameters. Let me explain with a sample code:

// Firebase dependencies
compile 'com.google.firebase:firebase-core:9.2.0'
compile 'com.google.firebase:firebase-database:9.2.0'

...

public class MainActivity extends AppCompatActivity {

    private FirebaseDatabase m_Database;
    private static boolean s_persistenceInitialized = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        m_Database = FirebaseDatabase.getInstance();

        if (!s_persistenceInitialized) {
            m_Database.setPersistenceEnabled(true);
            s_persistenceInitialized = true;
        }

        m_Database.setLogLevel(Level.DEBUG);
    }

    @Override
    protected void onStart() {
        super.onStart();

        long endAt = 100L; // Fixed value: CRASH on third app restart
    //  long endAt = new Date().getTime(); // Dynamic value: NO CRASH
        getGoal("min_per_day", endAt, "some_uid");
    }

    private void getGoal(String p_goalId, long p_endAt, String p_uid) {
        Query ref = m_Database.getReference("v0/data/meditation/goals").child(p_goalId).child(p_uid)
            .orderByChild("time").endAt(p_endAt).limitToLast(1);

        ref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.i("FB", "Snapshot: " + dataSnapshot);
            }

            @Override
            public void onCancelled(DatabaseError error) {
                Log.e("FB", "Error: " + error);
            }
        });
    }
}

So the fixed endAt param will crash the app on third start. I assume queries are cached to disk and then corrupted at some point if we recreate the same query from local cache multiple times (three). On the other hand, if endAt is not fixed, for example current time in millis, then everything works as expected. The same applies for startAt query parameter.

Electromechanical answered 13/7, 2016 at 10:6 Comment(1)
I've reported this to the Firebase support team and after some investigation, they confirmed that there is a bug here when enabling persistence while using the query endAt. They say they will hopefully fix it in a future release but they can't share any details or timelines at this time. Let's all hope it will be fixed soon, and until then we could probably avoid this with client side filtering.Electromechanical
H
14

UPDATE: It turns out there's another cause of this symptom, as mentioned by Kristijan in the comments. We've identified a bug where if you have a startAt() or endAt() call with an integer endpoint, e.g. startAt(10), it can trigger this sort of cache corruption. This bug will be fixed in the next release of the SDK. In the meantime, you may be able to use non-integer endpoints, e.g. startAt(10.001), as a workaround.

These symptoms match a known limitation with Firebase Realtime Database that prevents it from working if you have persistence enabled in multiple processes in an Android app.

Note that any Application.onCreate() code will run for every process in a multi-process android app, and so if your app is multi-process, you are initializing Firebase Database with persistence enabled in multiple processes and this is liable to lead to corruption of our offline cache and the hardAssert error that you are reporting.

Keep in mind that sometimes your app may be multi-process without you realizing it. For instance if you're using firebase-crash, it currently creates a background process for the purpose of reporting crashes more reliably, and so if you use firebase-crash, you now have a multi-process app. Other 3rd-party libraries could have similar behavior.

To test, you could add code to your Application.onCreate() something like:

System.out.println('INITIALIZING APP FROM PID: ' + android.os.Process.myPid());

If you see that logged twice in logcat (with two different PIDs) that means your app is running with multiple processes and you're hitting the limitation I mentioned.

As a workaround, you can either:

  1. Modify your app so that it only uses a single process.
  2. Remove your setPersistenceEnabled() code from your Application class and put it somewhere that will only be executed in your main process.

Note that you'll likely need to clear your app data to get rid of the hardAssert error once you've hit it, as the error indicates that the offline cache has gotten into an invalid state, so to fix it, you must clear it completely.

In an upcoming release, we have added better detection of this scenario so you'll get a much better error message. Additionally, firebase-crash will in the future avoid spawning a 2nd process, which may make this less likely to be an issue.

Hhour answered 13/7, 2016 at 16:26 Comment(3)
Thanks for the comment, but I seem to hit the hardAssert error without running a multi-process app. I can reproduce it in a clean new project. Firebase query with a fixed endAt parameter crashes on third app start consistently. Can you please comment on that?Electromechanical
You are right, thank you! I've updated my answer to mention this cause as well. Note that it only happens if you use startAt() or endAt() with an integer endpoint and it should be fixed in the next release.Hhour
Hi Michael. Just saw this error for the first time (app's been live for a month now), nothing critical at the moment, 1 crash instance for 1 user, but was wondering if this is still the case for this issue? I'm using v15.0.0 at the moment.Slam
H
11

I know it is an old post , i faced this issue and after some research , i upgraded my gradle to : implementation 'com.google.firebase:firebase-database:18.0.1' This helped the error go away. use the latest library. This Solved My Problem.

Helfant answered 6/8, 2019 at 19:55 Comment(1)
@SurajBahadur happy to help mate.Helfant
E
9

We are facing the same issue on version 9.0.2 and 9.2.0. After many hours of investigation, we found that one way to reproduce this issue is to have a query with fixed endAt and startAt parameters. Let me explain with a sample code:

// Firebase dependencies
compile 'com.google.firebase:firebase-core:9.2.0'
compile 'com.google.firebase:firebase-database:9.2.0'

...

public class MainActivity extends AppCompatActivity {

    private FirebaseDatabase m_Database;
    private static boolean s_persistenceInitialized = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        m_Database = FirebaseDatabase.getInstance();

        if (!s_persistenceInitialized) {
            m_Database.setPersistenceEnabled(true);
            s_persistenceInitialized = true;
        }

        m_Database.setLogLevel(Level.DEBUG);
    }

    @Override
    protected void onStart() {
        super.onStart();

        long endAt = 100L; // Fixed value: CRASH on third app restart
    //  long endAt = new Date().getTime(); // Dynamic value: NO CRASH
        getGoal("min_per_day", endAt, "some_uid");
    }

    private void getGoal(String p_goalId, long p_endAt, String p_uid) {
        Query ref = m_Database.getReference("v0/data/meditation/goals").child(p_goalId).child(p_uid)
            .orderByChild("time").endAt(p_endAt).limitToLast(1);

        ref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.i("FB", "Snapshot: " + dataSnapshot);
            }

            @Override
            public void onCancelled(DatabaseError error) {
                Log.e("FB", "Error: " + error);
            }
        });
    }
}

So the fixed endAt param will crash the app on third start. I assume queries are cached to disk and then corrupted at some point if we recreate the same query from local cache multiple times (three). On the other hand, if endAt is not fixed, for example current time in millis, then everything works as expected. The same applies for startAt query parameter.

Electromechanical answered 13/7, 2016 at 10:6 Comment(1)
I've reported this to the Firebase support team and after some investigation, they confirmed that there is a bug here when enabling persistence while using the query endAt. They say they will hopefully fix it in a future release but they can't share any details or timelines at this time. Let's all hope it will be fixed soon, and until then we could probably avoid this with client side filtering.Electromechanical
H
7

I too faced the same issue; After some point of time application was keep crashing on every launch. For time being I've disabled this database persistance. FirebaseDatabase.getInstance().setPersistenceEnabled(true).

I don't see any such strange crashes now!

Hope Firebase team will resolve this issue soon.

Heptachord answered 16/6, 2016 at 2:27 Comment(0)
O
3

This issue has been fixed in version 9.6. Check out the release notes.

However, when we enable the offline capabilities internet connection is still required for our app. Otherwise, write (at least) callbacks are never called.

Outofdoors answered 9/10, 2016 at 15:55 Comment(0)
H
0

Just for the record:

We solved the Uncaught exception in Firebase runloop (3.0.0) by removing following line

//remove this "feature" if you should use it
FirebaseApp.setAutomaticResourceManagmentEnabled(true)

API description:

If set to true it indicates that Firebase should close database connections automatically when the app is in the background. Disabled by default.

(Might be, that we missed some configurations for correct usage of this feature, but App is working as expected after not enabling the ResourceManagment)

Hagiographer answered 17/10, 2017 at 11:31 Comment(0)
C
-1

I have this problem, this method work if the install is new, and this method work if put the code how:

        FirebaseDatabase.getInstance().setPersistenceEnabled(true);
        FirebaseDatabase database = FirebaseDatabase.getInstance();

But if test in other device you need uninstall the app

Cosmogony answered 15/8, 2016 at 18:7 Comment(0)
C
-1

This fault is not from firebase, i simply got mine fixed by solving an uncaught NullPointerException in my program. Because when it throws an Exception while currently using firebase library, it misleads to firebase AssertionError. You need to debug your project carefully to solve this problem. And this seem to be compiler issue. However, you should try downgrading your Android Gradle Plugin to match the expected firebase library version i suspect.

Concrete answered 17/2, 2023 at 5:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.