Skip to content

lurch logs "published own bundle" even when no stanza is sent (silent PEP publish failure on Prosody) #194

Description

@nicorees

Summary

On an account hosted on Prosody, lurch never publishes its bundle or devicelist,
but reports success in the debug log. No <iq type='set'> publish ever reaches the
wire, and there is no error anywhere. The account ends up with no bundle node and
no entry in its own devicelist, so contacts cannot encrypt to it at all.

A second account in the same Pidgin instance, hosted on ejabberd, works correctly.
That gives a clean control: same plugin build, same Pidgin process, same session.

Environment

  • lurch: 0.7.0
  • Pidgin: 2.14.14
  • OS: Windows 11 Pro 25H2 build 26200.8875 Windows Feature Experience Pack 1000.26100.334.0
  • Failing account: Prosody (xmpp.xyz)
  • Working account: ejabberd (xmpp.jp)

Expected behaviour

On connect, lurch publishes its bundle to
eu.siacs.conversations.axolotl.bundles:<device id> and adds its device ID to
eu.siacs.conversations.axolotl.devicelist.

Actual behaviour

Neither node is ever written. The debug log reports the publish as successful.

Fetching the bundle node for the device ID that /lurch id show reports:

<iq type='get' id='b1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='eu.siacs.conversations.axolotl.bundles:DEVICE_ID'/>
  </pubsub>
</iq>
<iq to='USER@PROSODY_SERVER/RESOURCE' id='b1' type='error'>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>

Manually publishing the devicelist via the XMPP console works and persists, so the
server accepts these writes, they simply never leave Pidgin.

Steps to reproduce

  1. Add an account on a Prosody server that advertises the pubsub/pep identity on
    the account JID rather than on the server JID (see the disco comparison below).
  2. Enable lurch and connect.
  3. Fetch eu.siacs.conversations.axolotl.bundles:<device id> for that account
    → item-not-found.
  4. Grep the debug log for Sending and publish → no publish stanza for that account.

Debug log

lurch decides correctly and logs success, but nothing is sent:

lurch: lurch_pep_own_devicelist_request_handler: own id was missing, adding it
lurch: lurch_pep_own_devicelist_request_handler: devicelist needs publishing...
lurch: lurch_pep_own_devicelist_request_handler: ...done:
lurch: [AXC DEBUG] axc_bundle_collect: entered
lurch: [AXC DEBUG] axc_bundle_collect: leaving
lurch: lurch_bundle_publish_own: published own bundle for USER@PROSODY_SERVER

For the ejabberd account in the same log, the corresponding Sending (ssl) ... <iq type='set'> ... <publish node='eu.siacs.conversations.axolotl.bundles:...'> line is
present. For the Prosody account there is no such line, in either the
needs publishing or the already contained branch.

(The xmlns: URI eu.siacs.conversations.axolotl is not absolute parser warnings
appear for both accounts, including the working one, so they are unrelated, as the
README notes.)

Likely cause

jabber_pep_publish() returns void, so lurch cannot detect failure, and
src/lurch.c logs success unconditionally on the following line:

publish_node_bundle_p = xmlnode_from_str(bundle_xml, -1);
jabber_pep_publish(js_p, publish_node_bundle_p);

purple_debug_info("lurch", "%s: published own bundle for %s\n", __func__, uname);

The same pattern appears at the devicelist publish in src/lurch.c and in
lurch_api_id_remove_handler() in src/lurch_api.c.

As for why nothing is sent: libpurple gates PEP writes on JabberStream.pep, which
headers/jabber/jabber.h:232 documents as "does the local server support PEP?"
i.e. it is set from the server's disco#info. XEP-0163 places the pubsub/pep
identity on the account JID, which is where Prosody advertises it. Comparing the
two servers:

ejabberd, server JID (works):

<identity category='pubsub' type='pep'/>
<identity name='ejabberd' category='server' type='im'/>
<feature var='http://jabber.org/protocol/pubsub#publish'/>

Prosody, server JID (fails) no pubsub identity, no pubsub features at all:

<identity category='server' name='Prosody' type='im'/>

Prosody, account JID full PEP support, including #publish and #auto-create:

<identity category='account' type='registered'/>
<identity category='pubsub' type='pep'/>
<feature var='http://jabber.org/protocol/pubsub#publish'/>
<feature var='http://jabber.org/protocol/pubsub#auto-create'/>

I was not able to dive into libpurple's pep.c myself to confirm the early return on
!js->pep, so please treat that last step as inference. The unconditional success
log and the missing stanzas are directly observable either way.

Suggested fix

Send the publish IQ directly instead of going through jabber_pep_publish(), using
jabber_iq_new() / jabber_iq_send() which lurch already does for bundle
requests in lurch_bundle_request_do(). That avoids the flag entirely and allows
reporting server-side rejections instead of assuming success.

Possibly related

#193 reports the same user-visible symptom (empty devicelist, cannot send
encrypted) on ejabberd. It may or may not share this cause.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions