Fatal Exception: java.lang.NullPointerException: Attempt to invoke interface method 'java.util.List org.jivesoftware.smack.roster.rosterstore.RosterStore.a()' on a null object reference
at org.jivesoftware.smack.roster.Roster$RosterResultListener.onSuccess(SourceFile:1648)
at org.jivesoftware.smack.roster.Roster$RosterResultListener.onSuccess(SourceFile:1596)
at org.jivesoftware.smack.SmackFuture$1.run(SourceFile:151)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
mapping:
org.jivesoftware.smack.roster.rosterstore.RosterStore -> org.jivesoftware.smack.roster.rosterstore.RosterStore:
java.util.List getEntries() -> a
One possible way to trigger this is if the RosterStore is set to null while a versioned roster is retrieved. While it is not really someone should ever do, it is trivial to make Smack more robust against this.
Both reports include threads having this entry: org.jivesoftware.smack.tcp.XMPPTCPConnection.notifyConnectionError.
I don’t know much of Smack’s internals but, given the correlation, the cause of this crash may be related to a possible racing condition when a Roster response is being consumed just after the connection having been dropped.
I noticed one suspicious thing: my IDE can’t find any usage of the Roster#setRosterStore setter method from either my application of any other library in my dependency graph, suggesting this field is always null. I don’t initialize or even use Roster directly. I do use ChatManager though, which seems to use it.
Confirming: by adding a breakpoint to RosterResultListener#onSuccess, I can see the #rosterStore field is always null after a reload triggered by a connect+login.
I can’t find in AbstractXMPPConnection any code that clears its #syncRecvListeners and #asyncRecvListeners maps upon disconnections. If they’re really not cleared, a mismatched stanza may be delivered to a wrong listener that didn’t timeout yet after disconnecting and connecting the same AbstractXMPPConnection instance.
That would explain why RosterResultListener#onSuccess is getting a stanza that’s not a RosterPackage when it supposedly didn’t make any versioned request (as per Roster#reload's implementation when rosterStore is null)