powered by Jive Software

Smack-omemo 4.4.0 encounters null object reference while sending an omemo message

Please refer to the below link for more info:

The problem was reported by aTalk user while attempt to send an omemo message. aTalk displays an error message as shown below:

image

From the user debug log (see attach below) for tests on 1/12, below are my observations:
It seems that user clears all the omemo tables contents including the last active omemo device Id 1151002113 on 1/11.

Upon new launch of aTalk, omemo actually recreates a new OMEMO device ID 486745735; the new prekeys table was published onto the server and received a confirmation reply from server.

However what I observed is that when user try to send an omemo message, omemo seems to revert to use the old id 1151002113, hence the “null object reference” error; since there is no prekeys table for this device.

My expectation is that omemo should proceed to use the newly created id instead of the old deleted device id. Any explanation for this problem.

============ an extraction of atalk debug log =============
01-12 20:44:30.900 D/SMACK   ( 4684): SENT (3): 
01-12 20:44:30.900 D/SMACK   ( 4684): <iq id='S31TI-81' type='set'>
01-12 20:44:30.900 D/SMACK   ( 4684):   <pubsub xmlns='http://jabber.org/protocol/pubsub'>
01-12 20:44:30.900 D/SMACK   ( 4684):     <publish node='eu.siacs.conversations.axolotl.bundles:486745735'>
01-12 20:44:30.900 D/SMACK   ( 4684):       <item>
01-12 20:44:30.900 D/SMACK   ( 4684):         <bundle xmlns='eu.siacs.conversations.axolotl'>
01-12 20:44:30.900 D/SMACK   ( 4684):           <signedPreKeyPublic signedPreKeyId='1'>
01-12 20:44:30.900 D/SMACK   ( 4684):             BROyWRww+p/X85kSiDIyde+4Tf+pkn6LA71fDSZYRLcX
01-12 20:44:30.900 D/SMACK   ( 4684):           </signedPreKeyPublic>
....
K   ( 4684):             <preKeyPublic preKeyId='10'>
01-12 20:44:30.918 D/SMACK   ( 4684):               BTP5/jNfcpzYLP+E5jIxdjTZh5C/R1uGPKCq0qorCKM/
01-12 20:44:30.918 D/SMACK   ( 4684):             </preKeyPublic>
01-12 20:44:30.918 D/SMACK   ( 4684):           </prekeys>
01-12 20:44:30.918 D/SMACK   ( 4684):         </bundle>
01-12 20:44:30.918 D/SMACK   ( 4684):       </item>
01-12 20:44:30.918 D/SMACK   ( 4684):     </publish>
01-12 20:44:30.918 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:30.918 D/SMACK   ( 4684): </iq>
01-12 20:44:31.093 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:31.093 D/SMACK   ( 4684): <iq xml:lang='ru-RU' to='slavoon23@404.city/atalk' from='slavoon23@404.city' type='result' id='S31TI-81'>
01-12 20:44:31.093 D/SMACK   ( 4684):   <pubsub xmlns='http://jabber.org/protocol/pubsub'>
01-12 20:44:31.093 D/SMACK   ( 4684):     <publish node='eu.siacs.conversations.axolotl.bundles:486745735'>
01-12 20:44:31.093 D/SMACK   ( 4684):       <item id='64A739809846C'/>
01-12 20:44:31.093 D/SMACK   ( 4684):     </publish>
01-12 20:44:31.093 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:31.093 D/SMACK   ( 4684): </iq>
01-12 20:44:31.099 D/SMACK   ( 4684): SENT (3): 
01-12 20:44:31.099 D/SMACK   ( 4684): <iq id='PQK6M-8' type='get'>
01-12 20:44:31.099 D/SMACK   ( 4684):   <query xmlns='http://jabber.org/protocol/disco#info' node='eu.siacs.conversations.axolotl.devicelist'>
01-12 20:44:31.099 D/SMACK   ( 4684):   </query>
01-12 20:44:31.099 D/SMACK   ( 4684): </iq>
01-12 20:44:31.216 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:31.216 D/SMACK   ( 4684): <presence xml:lang='en' to='slavoon23@404.city/atalk' from='papamail@404.city/Conversations.g1ZX'>
01-12 20:44:31.216 D/SMACK   ( 4684):   <c xmlns='http://jabber.org/protocol/caps' node='http://conversations.im' hash='sha-1' ver='KWQQsqlerqQGIyKLIQTBsn7Adho='/>
01-12 20:44:31.216 D/SMACK   ( 4684):   <idle xmlns='urn:xmpp:idle:1' since='2021-01-12T17:44:03.785Z'/>
01-12 20:44:31.216 D/SMACK   ( 4684):   <x xmlns='vcard-temp:x:update'/>
01-12 20:44:31.216 D/SMACK   ( 4684):   <delay from='papamail@404.city/Conversations.g1ZX' stamp='2021-01-12T17:44:06.733508Z' xmlns='urn:xmpp:delay'/>
01-12 20:44:31.216 D/SMACK   ( 4684): </presence>
01-12 20:44:31.217 D/NativeCrypto( 4684): ssl=0x7f7e9d5300 sslRead buf=0x7f7ea3cb76 len=5258,timeo=0
01-12 20:44:31.218 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:31.218 D/SMACK   ( 4684): <message to='slavoon23@404.city/atalk' from='papamail@404.city' type='headline'>
01-12 20:44:31.218 D/SMACK   ( 4684):   <event xmlns='http://jabber.org/protocol/pubsub#event'>
01-12 20:44:31.218 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.devicelist'>
01-12 20:44:31.218 D/SMACK   ( 4684):       <item id='current'>
01-12 20:44:31.218 D/SMACK   ( 4684):         <list xmlns='eu.siacs.conversations.axolotl'>
01-12 20:44:31.218 D/SMACK   ( 4684):           <device id='1743131651'/>
01-12 20:44:31.218 D/SMACK   ( 4684):         </list>
01-12 20:44:31.218 D/SMACK   ( 4684):       </item>
01-12 20:44:31.218 D/SMACK   ( 4684):     </items>
01-12 20:44:31.218 D/SMACK   ( 4684):   </event>
01-12 20:44:31.218 D/SMACK   ( 4684):   <addresses xmlns='http://jabber.org/protocol/address'>
01-12 20:44:31.218 D/SMACK   ( 4684):     <address jid='papamail@404.city/Conversations.g1ZX' type='replyto'/>
01-12 20:44:31.218 D/SMACK   ( 4684):   </addresses>
01-12 20:44:31.218 D/SMACK   ( 4684): </message>
01-12 20:44:31.222 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:31.222 D/SMACK   ( 4684): <message to='slavoon23@404.city/atalk' from='slavoon23@404.city' type='headline'>
01-12 20:44:31.222 D/SMACK   ( 4684):   <event xmlns='http://jabber.org/protocol/pubsub#event'>
01-12 20:44:31.222 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.devicelist'>
01-12 20:44:31.222 D/SMACK   ( 4684):       <item id='64A42ED2444BF'>
01-12 20:44:31.222 D/SMACK   ( 4684):         <list xmlns='eu.siacs.conversations.axolotl'>
01-12 20:44:31.222 D/SMACK   ( 4684):           <device id='1151002113'/>
01-12 20:44:31.222 D/SMACK   ( 4684):           <device id='486745735'/>
01-12 20:44:31.222 D/SMACK   ( 4684):           <device id='909412898'/>
01-12 20:44:31.222 D/SMACK   ( 4684):           <device id='935698264'/>
01-12 20:44:31.222 D/SMACK   ( 4684):         </list>
01-12 20:44:31.222 D/SMACK   ( 4684):       </item>
01-12 20:44:31.222 D/SMACK   ( 4684):     </items>
01-12 20:44:31.222 D/SMACK   ( 4684):   </event>
01-12 20:44:31.222 D/SMACK   ( 4684):   <addresses xmlns='http://jabber.org/protocol/address'>
01-12 20:44:31.222 D/SMACK   ( 4684):     <address jid='slavoon23@404.city/atalk' type='replyto'/>
01-12 20:44:31.222 D/SMACK   ( 4684):   </addresses>
01-12 20:44:31.222 D/SMACK   ( 4684): </message>
01-12 20:44:31.313 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:31.313 D/SMACK   ( 4684): <iq xml:lang='ru-RU' to='slavoon23@404.city/atalk' from='slavoon23@404.city' type='result' id='PQK6M-8'>
01-12 20:44:31.313 D/SMACK   ( 4684):   <query node='eu.siacs.conversations.axolotl.devicelist' xmlns='http://jabber.org/protocol/disco#info'>
01-12 20:44:31.313 D/SMACK   ( 4684):     <identity type='pep' category='pubsub'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <identity type='leaf' category='pubsub'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <identity type='registered' category='account'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/rsm'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#create-nodes'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#auto-create'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#auto-subscribe'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#delete-nodes'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#delete-items'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#filtered-notifications'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#modify-affiliations'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#outcast-affiliation'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#persistent-items'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#publish'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#publish-options'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#purge-nodes'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retract-items'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-affiliations'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-items'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-subscriptions'/>
01-12 20:44:31.313 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#subscribe'/>
01-12 20:44:31.313 D/SMACK   ( 4684):   </query>
01-12 20:44:31.313 D/SMACK   ( 4684): </iq>
01-12 20:44:31.315 D/SMACK   ( 4684): SENT (3): 
01-12 20:44:31.315 D/SMACK   ( 4684): <iq id='S31TI-85' type='get'>
01-12 20:44:31.315 D/SMACK   ( 4684):   <pubsub xmlns='http://jabber.org/protocol/pubsub'>
01-12 20:44:31.315 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.devicelist'/>
01-12 20:44:31.315 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:31.315 D/SMACK   ( 4684): </iq>
01-12 20:44:31.329 D/SMACK   ( 4684): <message to='slavoon23@404.city/atalk' from='papamail@404.city' type='headline'>
01-12 20:44:31.329 D/SMACK   ( 4684):   <event xmlns='http://jabber.org/protocol/pubsub#event'>
01-12 20:44:31.329 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.devicelist'>
01-12 20:44:31.329 D/SMACK   ( 4684):       <item id='current'>
01-12 20:44:31.329 D/SMACK   ( 4684):         <list xmlns='eu.siacs.conversations.axolotl'>
01-12 20:44:31.329 D/SMACK   ( 4684):           <device id='1743131651'/>
01-12 20:44:31.329 D/SMACK   ( 4684):         </list>
01-12 20:44:31.329 D/SMACK   ( 4684):       </item>
01-12 20:44:31.329 D/SMACK   ( 4684):     </items>
01-12 20:44:31.329 D/SMACK   ( 4684):   </event>
01-12 20:44:31.329 D/SMACK   ( 4684):   <addresses xmlns='http://jabber.org/protocol/address'>
01-12 20:44:31.329 D/SMACK   ( 4684):     <address jid='papamail@404.city/Conversations.g1ZX' type='replyto'/>
01-12 20:44:31.329 D/SMACK   ( 4684):   </addresses>
01-12 20:44:31.329 D/SMACK   ( 4684): </message>
01-12 20:44:31.333 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:31.333 D/SMACK   ( 4684): <message to='slavoon23@404.city/atalk' from='slavoon23@404.city' type='headline'>
01-12 20:44:31.333 D/SMACK   ( 4684):   <event xmlns='http://jabber.org/protocol/pubsub#event'>
01-12 20:44:31.333 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.devicelist'>
01-12 20:44:31.333 D/SMACK   ( 4684):       <item id='64A42ED2444BF'>
01-12 20:44:31.333 D/SMACK   ( 4684):         <list xmlns='eu.siacs.conversations.axolotl'>
01-12 20:44:31.333 D/SMACK   ( 4684):           <device id='1151002113'/>
01-12 20:44:31.333 D/SMACK   ( 4684):           <device id='486745735'/>
01-12 20:44:31.333 D/SMACK   ( 4684):           <device id='909412898'/>
01-12 20:44:31.333 D/SMACK   ( 4684):           <device id='935698264'/>
01-12 20:44:31.333 D/SMACK   ( 4684):         </list>
01-12 20:44:31.333 D/SMACK   ( 4684):       </item>
01-12 20:44:31.333 D/SMACK   ( 4684):     </items>
01-12 20:44:31.333 D/SMACK   ( 4684):   </event>
01-12 20:44:31.333 D/SMACK   ( 4684):   <addresses xmlns='http://jabber.org/protocol/address'>
01-12 20:44:31.333 D/SMACK   ( 4684):     <address jid='slavoon23@404.city/atalk' type='replyto'/>
01-12 20:44:31.333 D/SMACK   ( 4684):   </addresses>
01-12 20:44:31.333 D/SMACK   ( 4684): </message>
01-12 20:44:31.505 D/SMACK   ( 4684): <iq xml:lang='ru-RU' to='slavoon23@404.city/atalk' from='slavoon23@404.city' type='result' id='S31TI-85'>
01-12 20:44:31.505 D/SMACK   ( 4684):   <pubsub xmlns='http://jabber.org/protocol/pubsub'>
01-12 20:44:31.505 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.devicelist'>
01-12 20:44:31.505 D/NativeCrypto( 4684): ssl=0x7f7e9d5300 sslRead buf=0x7f7ea3c000 len=8192,timeo=0
01-12 20:44:31.506 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:31.506 D/SMACK   ( 4684):       <item id='64A42ED2444BF'>
01-12 20:44:31.506 D/SMACK   ( 4684):         <list xmlns='eu.siacs.conversations.axolotl'>
01-12 20:44:31.506 D/SMACK   ( 4684):           <device id='1151002113'/>
01-12 20:44:31.506 D/SMACK   ( 4684):           <device id='486745735'/>
01-12 20:44:31.506 D/SMACK   ( 4684):           <device id='909412898'/>
01-12 20:44:31.506 D/SMACK   ( 4684):           <device id='935698264'/>
01-12 20:44:31.506 D/SMACK   ( 4684):         </list>
01-12 20:44:31.506 D/SMACK   ( 4684):       </item>
01-12 20:44:31.506 D/SMACK   ( 4684):     </items>
01-12 20:44:31.506 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:31.506 D/SMACK   ( 4684): </iq>
01-12 20:44:31.530 I/(DatabaseBackend.java:1041)#storeCachedDeviceList( 4684): Identities table updated for inactiveDevice: slavoon23@404.city:[]
01-12 20:44:31.555 I/(DatabaseBackend.java:1041)#storeCachedDeviceList( 4684): Identities table updated for inactiveDevice: slavoon23@404.city:[]
01-12 20:44:31.562 I/(DatabaseBackend.java:1041)#storeCachedDeviceList( 4684): Identities table updated for inactiveDevice: papamail@404.city:[]
01-12 20:44:31.581 I/(DatabaseBackend.java:1041)#storeCachedDeviceList( 4684): Identities table updated for inactiveDevice: slavoon23@404.city:[]
01-12 20:44:31.586 I/(DatabaseBackend.java:1041)#storeCachedDeviceList( 4684): Identities table updated for inactiveDevice: papamail@404.city:[]
01-12 20:44:31.610 I/(DatabaseBackend.java:1041)#storeCachedDeviceList( 4684): Identities table updated for inactiveDevice: slavoon23@404.city:[]
01-12 20:44:31.629 I/(DatabaseBackend.java:1041)#storeCachedDeviceList( 4684): Identities table updated for inactiveDevice: slavoon23@404.city:[]
01-12 20:44:31.654 I/(DatabaseBackend.java:1041)#storeCachedDeviceList( 4684): Identities table updated for inactiveDevice: slavoon23@404.city:[]
01-12 20:44:32.141 D/SMACK   ( 4684): SENT (3): 
01-12 20:44:32.141 D/SMACK   ( 4684): <iq to='papamail@404.city' id='PQK6M-10' type='get'>
01-12 20:44:32.141 D/SMACK   ( 4684):   <query xmlns='http://jabber.org/protocol/disco#info' node='eu.siacs.conversations.axolotl.devicelist'>
01-12 20:44:32.141 D/SMACK   ( 4684):   </query>
01-12 20:44:32.141 D/SMACK   ( 4684): </iq>
01-12 20:44:32.258 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:32.258 D/SMACK   ( 4684): <iq xml:lang='ru-RU' to='slavoon23@404.city/atalk' from='papamail@404.city' type='result' id='PQK6M-10'>
01-12 20:44:32.258 D/SMACK   ( 4684):   <query node='eu.siacs.conversations.axolotl.devicelist' xmlns='http://jabber.org/protocol/disco#info'>
01-12 20:44:32.258 D/SMACK   ( 4684):     <identity type='pep' category='pubsub'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <identity type='leaf' category='pubsub'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <identity type='registered' category='account'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/rsm'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#create-nodes'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#auto-create'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#auto-subscribe'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#delete-nodes'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#delete-items'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#filtered-notifications'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#modify-affiliations'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#outcast-affiliation'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#persistent-items'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#publish'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#publish-options'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#purge-nodes'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retract-items'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-affiliations'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-items'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-subscriptions'/>
01-12 20:44:32.258 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#subscribe'/>
01-12 20:44:32.258 D/SMACK   ( 4684):   </query>
01-12 20:44:32.258 D/SMACK   ( 4684): </iq>
01-12 20:44:32.260 D/SMACK   ( 4684): SENT (3): 
01-12 20:44:32.260 D/SMACK   ( 4684): <iq to='papamail@404.city' id='S31TI-87' type='get'>
01-12 20:44:32.260 D/SMACK   ( 4684):   <pubsub xmlns='http://jabber.org/protocol/pubsub'>
01-12 20:44:32.260 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.devicelist'/>
01-12 20:44:32.260 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:32.260 D/SMACK   ( 4684): </iq>
01-12 20:44:32.367 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:32.367 D/SMACK   ( 4684): <iq xml:lang='ru-RU' to='slavoon23@404.city/atalk' from='papamail@404.city' type='result' id='S31TI-87'>
01-12 20:44:32.367 D/SMACK   ( 4684):   <pubsub xmlns='http://jabber.org/protocol/pubsub'>
01-12 20:44:32.367 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.devicelist'>
01-12 20:44:32.367 D/SMACK   ( 4684):       <item id='current'>
01-12 20:44:32.367 D/SMACK   ( 4684):         <list xmlns='eu.siacs.conversations.axolotl'>
01-12 20:44:32.367 D/SMACK   ( 4684):           <device id='1743131651'/>
01-12 20:44:32.367 D/SMACK   ( 4684):         </list>
01-12 20:44:32.367 D/SMACK   ( 4684):       </item>
01-12 20:44:32.367 D/SMACK   ( 4684):     </items>
01-12 20:44:32.367 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:32.367 D/SMACK   ( 4684): </iq>
01-12 20:44:34.702 D/SMACK   ( 4684): SENT (3): 
01-12 20:44:34.702 D/SMACK   ( 4684): <iq id='PQK6M-11' type='get'>
01-12 20:44:34.702 D/SMACK   ( 4684):   <query xmlns='http://jabber.org/protocol/disco#info' node='eu.siacs.conversations.axolotl.bundles:1151002113'>
01-12 20:44:34.702 D/SMACK   ( 4684):   </query>
01-12 20:44:34.702 D/SMACK   ( 4684): </iq>
01-12 20:44:34.819 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:34.819 D/SMACK   ( 4684): <iq xml:lang='ru-RU' to='slavoon23@404.city/atalk' from='slavoon23@404.city' type='result' id='PQK6M-11'>
01-12 20:44:34.819 D/SMACK   ( 4684):   <query node='eu.siacs.conversations.axolotl.bundles:1151002113' xmlns='http://jabber.org/protocol/disco#info'>
01-12 20:44:34.819 D/SMACK   ( 4684):     <identity type='pep' category='pubsub'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <identity type='leaf' category='pubsub'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <identity type='registered' category='account'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/rsm'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#create-nodes'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#auto-create'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#auto-subscribe'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#delete-nodes'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#delete-items'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#filtered-notifications'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#modify-affiliations'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#outcast-affiliation'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#persistent-items'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#publish'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#publish-options'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#purge-nodes'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retract-items'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-affiliations'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-items'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#retrieve-subscriptions'/>
01-12 20:44:34.819 D/SMACK   ( 4684):     <feature var='http://jabber.org/protocol/pubsub#subscribe'/>
01-12 20:44:34.819 D/SMACK   ( 4684):   </query>
01-12 20:44:34.819 D/SMACK   ( 4684): </iq>
01-12 20:44:34.822 D/SMACK   ( 4684): SENT (3): 
01-12 20:44:34.822 D/SMACK   ( 4684): <iq id='S31TI-89' type='get'>
01-12 20:44:34.822 D/SMACK   ( 4684):   <pubsub xmlns='http://jabber.org/protocol/pubsub'>
01-12 20:44:34.822 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.bundles:1151002113'/>
01-12 20:44:34.822 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:34.822 D/SMACK   ( 4684): </iq>
01-12 20:44:34.928 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:34.928 D/SMACK   ( 4684): <iq xml:lang='ru-RU' to='slavoon23@404.city/atalk' from='slavoon23@404.city' type='result' id='S31TI-89'>
01-12 20:44:34.928 D/SMACK   ( 4684):   <pubsub xmlns='http://jabber.org/protocol/pubsub'>
01-12 20:44:34.928 D/SMACK   ( 4684):     <items node='eu.siacs.conversations.axolotl.bundles:1151002113'/>
01-12 20:44:34.928 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:34.928 D/SMACK   ( 4684): </iq>
01-12 20:44:34.929 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:34.929 D/SMACK   ( 4684): <r xmlns='urn:xmpp:sm:3'/>
01-12 20:44:34.929 W/(ChatController.java:316)#sendMessage( 4684): Send instant message exception: Attempt to invoke virtual method 'java.util.HashMap org.jivesoftware.smackx.omemo.element.OmemoBundleElement.getPreKeys()' on a null object reference

Can you provide a stracktrace of the NPE?

The problem happens on user device. I am unable to produce the problem on my side. The only info I have is the problem description (aTalk issues list) and the debug log which I have extracted the relevant info. I can send you the log if you want to.

Unfortunately the debug log you showed does not contain the stacktrace. This is maybe due the exception not being logged with its stacktrace, but, e.g. only the exception message being logged.

With reference to the getPreKeys(), it seems the “null object reference” is due to preKeysB64 is null. I see that this is being initialized in the OmemoBundleElement constructor.

I am not sure when the OmemoBundleElement class is being called.
Assuming my interpretation of the debug log is correct. From the user debug log, there are a total of 4 omemo devices i.e.

01-12 20:44:31.506 D/SMACK ( 4684):
01-12 20:44:31.506 D/SMACK ( 4684):
01-12 20:44:31.506 D/SMACK ( 4684):
01-12 20:44:31.506 D/SMACK ( 4684):

The prekeys table for id 1151002113 is empty, as user has performed a new init of OMEMO tables.
The last two id’s are inactive. However I see that OMEMO does create a new device id i.e. 486745735 with prekeys generated on aTalk launch. Any reason why preKeysB64 is not initialized with this newly generated prekeys data. It seems OMEMO continues to use the old device id i.e. 1151002113; hence subsequent omemo message sending will again trigger the ‘null object reference’.

I am not familiar with the OMEMO process flow, a bit lost in this area.

    public HashMap<Integer, byte[]> getPreKeys() {
        if (preKeys == null) {
            preKeys = new HashMap<>();
            for (int id : preKeysB64.keySet()) {
                preKeys.put(id, Base64.decode(preKeysB64.get(id)));
            }
        }
        return this.preKeys;
    }

Maybe you are reusing the old OmemoManager instance which still has the old deviceID?

I have specifically to requested user to exit aTalk before start up aTalk again. From the debug log, it confirms user did terminated aTalk before start up aTalk. I also requested the user to clear aTalk cache data and restart aTalk; in case omemo is using cached info. However none of these help. User still faces ‘null object reference’ whenever he attempts to send an omemo message from aTalk. The whole problem seems to point to that “preKeysB64” is null and not being initialized.

My previous message does not show the info due to “<” in text, I reattached here again.

01-12 20:44:31.506 D/SMACK   ( 4684): RECV (3): 
01-12 20:44:31.506 D/SMACK   ( 4684):       <item id='64A42ED2444BF'>
01-12 20:44:31.506 D/SMACK   ( 4684):         <list xmlns='eu.siacs.conversations.axolotl'>
01-12 20:44:31.506 D/SMACK   ( 4684):           <device id='1151002113'/>
01-12 20:44:31.506 D/SMACK   ( 4684):           <device id='486745735'/>
01-12 20:44:31.506 D/SMACK   ( 4684):           <device id='909412898'/>
01-12 20:44:31.506 D/SMACK   ( 4684):           <device id='935698264'/>
01-12 20:44:31.506 D/SMACK   ( 4684):         </list>
01-12 20:44:31.506 D/SMACK   ( 4684):       </item>
01-12 20:44:31.506 D/SMACK   ( 4684):     </items>
01-12 20:44:31.506 D/SMACK   ( 4684):   </pubsub>
01-12 20:44:31.506 D/SMACK   ( 4684): </iq>

can you verify that your storage backend is functioning correctly?

I have actually performed at least two times, testing each method to ensure it works as expected. I have done detailed source review/walk-through at least 3 times, comparing each method functionality with omemo file-based method to ensure there is no error in the source. I am quite confident that the above observed problems is not due to aTalk backend database support.

I did once attempt to include unit test into aTalk, but found that this needs quite a change to aTalk source. I decided not to do this, as it may done more harm than good, and created other hidden problems. Eventually I aborted the attempt.

In my previous comment (attached below), may be you can enlighten me when and under what conditions the constructor is being called. This can help me to verify aTalk other part of code, to ensure aTalk fulfilled this requirements.

With reference to the getPreKeys(), it seems the “null object reference” is due to preKeysB64 is null. I see that this is being initialized in the OmemoBundleElement constructor.

Please also note, the user mentioned that he re-init the whole omemo mysql tables (clean and restart aTalk); similar to a case when a new user is added, and omemo manager is called to re-create the table upon user log in to the service. I am no sure if this has put omemo routine out of sync with the data due to omemo own cached data. I did ask user the clear the aTalk cache, but is not helping.

I am now asking user to perform the “OMEMO Identity Regeneration”, to see if this unlocked the problem.

I now see what may cause your problem.
The issue is probably caused by your own OmemoStore implementation not removing the old deviceId from storage.

The error you see can happen if localDeviceIdsOf(jid) returns a set that also contains the old deviceId, which no longer has prekeys and other data stored.

As a fix you should verify that you are removing the old device ID from your store when purging the identity. Note that if you are wrapping your OmemoStore in a CachingOmemoStore, you have to restart the android application to verify if it is working, as the CachingOmemoStore could otherwise hide the malfunctioning of your implementation.

Thanks for info.

aTalk does not wrap OmemoStore with CachingOmemoStore. I compared aTalk OmemoStore implementations against smack omemo FileBaseOmemoStore, i.e.
a. storeCachedDeviceList()
b, localDeviceIdsOf()

As the start of Omemo init, method (a) is being called. I see that (a) only marks the deviceId as inactive, but not deleting the file. I am unable to figure out how method (b) filtered out the inactive devices; aTalk follows exactly the same implementations.

In your comment, are you propose that localDeviceIdsOf() must filter out the inactive devices before returning the deviceIds result;

Or your “the old deviceId” refers to something else; and which FileBaseOmemoStore is responsible of removing the old deviceId.

================ aTalk log for storeCachedDeviceList() ==========
2021-01-19 07:38:33.919 25417-22289/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: swordfish@atalk.sytes.net:[1245216054]
2021-01-19 07:38:33.922 25417-22289/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: swordfish@atalk.sytes.net:[]
2021-01-19 07:38:33.926 25417-22289/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: swordfish@atalk.sytes.net:[1245216054]
2021-01-19 07:38:33.927 25417-22289/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: swordfish@atalk.sytes.net:[]
2021-01-19 07:38:33.927 25417-22300/org.atalk.android W/g.atalk.androi: Long monitor contention with owner Thread-25 (22289) at void org.jivesoftware.smackx.omemo.OmemoManager.initialize()(OmemoManager.java:-1) waiters=0 in org.jivesoftware.smackx.omemo.internal.OmemoDevice org.jivesoftware.smackx.omemo.OmemoManager.getOwnDevice() for 387ms
2021-01-19 07:38:33.928 25417-22289/org.atalk.android D/(AndroidOmemoService.java:113)#initializationFinished: Initialize OmemoManager successful for swordfish@atalk.sytes.net/atalk
2021-01-19 07:38:33.928 25417-22301/org.atalk.android W/g.atalk.androi: Long monitor contention with owner Thread-25 (22289) at void org.jivesoftware.smackx.omemo.OmemoManager.initialize()(OmemoManager.java:-1) waiters=2 in org.jivesoftware.smackx.omemo.internal.OmemoDevice org.jivesoftware.smackx.omemo.OmemoManager.getOwnDevice() for 264ms
2021-01-19 07:38:33.950 25417-22301/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: peacock@atalk.sytes.net:[1701516316, 328590658]
2021-01-19 07:38:33.953 25417-22302/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: hawk@atalk.sytes.net:[43395281]
2021-01-19 07:38:33.955 25417-22288/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: xyz123@atalk.sytes.net:[1362032407]
2021-01-19 07:38:33.957 25417-22279/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: swordfish@atalk.sytes.net:[1245216054]
2021-01-19 07:38:33.958 25417-22300/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: parrot@atalk.sytes.net:[116536437, 1566361092, 1741875658, 1203482097, 889121650, 522622186]
2021-01-19 07:38:33.960 25417-22303/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: kingfisher@atalk.sytes.net:[404190446]
2021-01-19 07:38:33.970 25417-22288/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: xyz123@atalk.sytes.net:[]
2021-01-19 07:38:33.973 25417-22302/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: hawk@atalk.sytes.net:[]
2021-01-19 07:38:33.973 25417-22279/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: swordfish@atalk.sytes.net:[]
2021-01-19 07:38:33.976 25417-22303/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: kingfisher@atalk.sytes.net:[92793923]
2021-01-19 07:38:33.980 25417-22301/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: peacock@atalk.sytes.net:[421888194]
2021-01-19 07:38:33.992 25417-22288/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: xyz123@atalk.sytes.net:[1362032407]
2021-01-19 07:38:33.993 25417-22302/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: hawk@atalk.sytes.net:[43395281]
2021-01-19 07:38:34.003 25417-22288/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: xyz123@atalk.sytes.net:[]
2021-01-19 07:38:34.007 25417-22303/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: kingfisher@atalk.sytes.net:[404190446]
2021-01-19 07:38:34.008 25417-22302/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: hawk@atalk.sytes.net:[]
2021-01-19 07:38:34.010 25417-22300/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: parrot@atalk.sytes.net:[1156361481]
2021-01-19 07:38:34.011 25417-22301/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: peacock@atalk.sytes.net:[1701516316, 328590658]
2021-01-19 07:38:34.012 25417-22303/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: kingfisher@atalk.sytes.net:[92793923]
2021-01-19 07:38:34.014 25417-22279/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: swordfish@atalk.sytes.net:[1245216054]
2021-01-19 07:38:34.016 25417-22301/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: peacock@atalk.sytes.net:[421888194]
2021-01-19 07:38:34.021 25417-22279/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: swordfish@atalk.sytes.net:[]
2021-01-19 07:38:34.024 25417-22300/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: parrot@atalk.sytes.net:[116536437, 1566361092, 1741875658, 1203482097, 889121650, 522622186]
2021-01-19 07:38:34.028 25417-22279/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: swordfish@atalk.sytes.net:[1245216054]
2021-01-19 07:38:34.030 25417-22279/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: swordfish@atalk.sytes.net:[]
2021-01-19 07:38:34.032 25417-22300/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: parrot@atalk.sytes.net:[1156361481]
2021-01-19 07:38:34.037 25417-22279/org.atalk.android D/(DatabaseBackend.java:1012)#storeCachedDeviceList: Identities table - updating for activeDevice: swordfish@atalk.sytes.net:[1245216054]
2021-01-19 07:38:34.038 25417-22279/org.atalk.android I/(DatabaseBackend.java:1041)#storeCachedDeviceList: Identities table updated for inactiveDevice: swordfish@atalk.sytes.net:[]

============== smack Omemo FileFileBaseOmemoStoreBase ====================

    @Override
    public void storeCachedDeviceList(OmemoDevice userDevice,
                                      BareJid contact,
                                      OmemoCachedDeviceList contactsDeviceList) throws IOException {
        if (contact == null) {
            return;
        }

        File activeDevices = hierarchy.getContactsActiveDevicesPath(userDevice, contact);
        writeIntegers(activeDevices, contactsDeviceList.getActiveDevices());

        File inactiveDevices = hierarchy.getContactsInactiveDevicesPath(userDevice, contact);
        writeIntegers(inactiveDevices, contactsDeviceList.getInactiveDevices());
    }

    @Override
    public SortedSet<Integer> localDeviceIdsOf(BareJid localUser) {
        SortedSet<Integer> deviceIds = new TreeSet<>();
        File userDir = hierarchy.getUserDirectory(localUser);
        File[] list = userDir.listFiles();
        for (File d : list != null ? list : new File[] {}) {
            if (d.isDirectory()) {
                try {
                    deviceIds.add(Integer.parseInt(d.getName()));
                } catch (NumberFormatException e) {
                    // ignore
                }
            }
        }
        return deviceIds;
    }

============== aTalk Omemo SQLiteOmemoStore ====================

    public void storeCachedDeviceList(OmemoDevice userDevice, BareJid contact, OmemoCachedDeviceList deviceList)
    {
        if (contact == null) {
            return;
        }

        final SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        // Active devices
        values.put(SQLiteOmemoStore.ACTIVE, 1);
        Set<Integer> activeDevices = deviceList.getActiveDevices();
        Timber.d("Identities table - updating for activeDevice: %s:%s", contact, activeDevices);
        for (int deviceId : activeDevices) {
            String[] selectionArgs = {contact.toString(), Integer.toString(deviceId)};

            int row = db.update(SQLiteOmemoStore.IDENTITIES_TABLE_NAME, values,
                    SQLiteOmemoStore.BARE_JID + "=? AND " + SQLiteOmemoStore.DEVICE_ID + "=?",
                    selectionArgs);

            if (row == 0) {
                /*
                 * Just logged the error. Any missing buddy identityKey will be handled by
                 * AndroidOmemoService#buddyDeviceListUpdateListener()
                 */
                Timber.d("Identities table - create new activeDevice: %s:%s ", contact, deviceId);
                values.put(SQLiteOmemoStore.BARE_JID, contact.toString());
                values.put(SQLiteOmemoStore.DEVICE_ID, deviceId);
                db.insert(SQLiteOmemoStore.IDENTITIES_TABLE_NAME, null, values);
            }
        }

        /*
         * Inactive devices:
         * Important: Must clear values before use, otherwise update exiting deviceID with new deviceID but still keeping
         * old fingerPrint and identityKey. This forbids update of the fingerPrint and IdentityKey for the new deviceID,
         * Worst it causes aTalk to crash on next access to omemo chat with the identity
         */
        values.clear();
        values.put(SQLiteOmemoStore.ACTIVE, 0);
        Set<Integer> inActiveDevices = deviceList.getInactiveDevices();
        Timber.i("Identities table updated for inactiveDevice: %s:%s", contact, inActiveDevices);
        for (int deviceId : inActiveDevices) {
            String[] selectionArgs = {contact.toString(), Integer.toString(deviceId)};

            int row = db.update(SQLiteOmemoStore.IDENTITIES_TABLE_NAME, values,
                    SQLiteOmemoStore.BARE_JID + "=? AND " + SQLiteOmemoStore.DEVICE_ID + "=?",
                    selectionArgs);
            if (row == 0) {
                Timber.w("Identities table contains no inactiveDevice (create new): %s:%s", contact, deviceId);
                values.put(SQLiteOmemoStore.BARE_JID, contact.toString());
                values.put(SQLiteOmemoStore.DEVICE_ID, deviceId);
                db.insert(SQLiteOmemoStore.IDENTITIES_TABLE_NAME, null, values);
            }
        }
    }
    @Override
    public SortedSet<Integer> localDeviceIdsOf(BareJid localUser)
    {
        return mDB.loadDevideIdsOf(localUser);
    }

    /* mDB method implementation */
    public SortedSet<Integer> loadDevideIdsOf(BareJid user)
    {
        SortedSet<Integer> deviceIds = new TreeSet<>();
        int registrationId;
        String ORDER_ASC = SQLiteOmemoStore.OMEMO_REG_ID + " ASC";

        SQLiteDatabase db = this.getReadableDatabase();
        String[] columns = {SQLiteOmemoStore.OMEMO_REG_ID};
        String[] selectionArgs = {user.toString()};

        Cursor cursor = db.query(SQLiteOmemoStore.OMEMO_DEVICES_TABLE_NAME, columns,
                SQLiteOmemoStore.OMEMO_JID + "=?", selectionArgs, null, null, ORDER_ASC);

        while (cursor.moveToNext()) {
            registrationId = cursor.getInt(0);
            deviceIds.add(registrationId);
        }
        cursor.close();
        return deviceIds;
    }

Note that localDeviceIdsOf(jid) is only supposed to return IDs of the local device and has nothing to do with the device list.
In almost all scenarios, this method returns a single device ID (that of the users account). It is only due to Smacks ability to have more than one OmemoManager per connection that this method returns a set. More than one device ID is only useful for testing.

So in order to fix your issue, make sure that your purgeIdentity implementation deletes the userId directory which is otherwise being added to the set in

deviceIds.add(Integer.parseInt(d.getName()));

of the localDevicesOf(localUser) method.

Thanks for the clarification. There was a mistake in my previous comment, localDeviceIdsOf() actually uses the OMEMO_DEVICES_TABLE_NAME, where it contains the deviceId’s of all the registered user accounts in aTalk; and not the IDENTITIES_TABLE_NAME which I was referred to in my previous comment.

I review all the current aTalk source that deals with OMEMO_DEVICES_TABLE_NAME, this table will only contain a single deviceId for each registered user account; These apply to all the functions below that access this table:

a. When user removes an existing registered user account, all deviceId’s of this user account are removed from the table; user is also blocked to add the same account twice.,
b. During Omemo Identity regeneration; all existing deviceId’s of the selected user account are removed from the OMEMO_DEVICES_TABLE_NAME, before a new one is created.
c. Purge Omemo databse; which removes all the Omemo tables in database before new tables are created.

Look like user problem is due to something else. Else, an Omemo Identity Regeneration should fix this problem.

Just in case, I have changed the unique constraint when creating the OMEMO_DEVICES_TABLE_NAME to depend on user account only.

Please see the latest feedback from user in aTalk issue list:
In short the “Regenerate OMEMO iddentities” does not seem to help.

By the way, any latest upate on the following:
Smack Omemo causes system crashes when buddy prekeys is empty or corrupted)

The “Purge unused identities” option finally gets the user device omemo encryption to working order.

Looking back to all the history, user omemo problem can either due to one or a combination of the problems below:
a. Own omemo device IdentityKeyPair is corrupted
b. Contact’s device IdentityKey is corrupted or has null value
c. Local omemo database is not insync with the published key bundle on the server.

Please see the latest aTalk update.