An error upon downloading from a PEP node

Greetings.

This error appears, after Chawan downloads data from a given PubSub node.

     at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.108.Final.jar:4.1.108.Final]
    at java.lang.Thread.run(Thread.java:840) [?:?]
2026.03.03 13:22:00.801 ERROR [socket_c2s_ssl-thread-4]: org.jivesoftware.openfire.nio.NettyConnection - Problem during connection close or cleanup
java.nio.channels.ClosedChannelException: null
    at io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1156) ~[netty-handler-4.1.108.Final.jar:4.1.108.Final] 

This is the script which is being executed.

#!/usr/bin/env python3
# coding: utf-8
#
# Usage:
#
# printf "xmpp:pubsub.movim.eu?;node=berlin-xmpp-meetup" | python pubsub.py > berlin-xmpp-meetup.pubsub
#

import asyncio
import configparser
import datetime
import os
import select
import sys
from urllib.parse import urlparse
import xml.etree.ElementTree as ET

class Chawan:

    def directives(cha_control, content=None, content_type=None, status_code=None) -> None:
        if status_code:
            sys.stdout.write(f"Status: {status_code}\n")
        sys.stdout.write(f"Cha-Control: {cha_control}\n")
        if content_type:
            sys.stdout.write(f"Content-Type: {content_type}\n")
        if content:
            sys.stdout.write("\n")
            sys.stdout.write(content)
            sys.stdout.write("\n")
        sys.stdout.flush()
        sys.exit()

try:
    from slixmpp import ClientXMPP
    from slixmpp.exceptions import IqError, IqTimeout
    from slixmpp.stanza.iq import Iq
    #from slixmpp.xmlstream import ET
except Exception as e:
    cha_control = f"ConnectionError InternalError {str(e)}"
    content = content_type = status_code = None
    Chawan.directives(cha_control, content, content_type, status_code)

class Xmpp:

    async def pubsub(
        client_xmpp: ClientXMPP, jid_bare: str, node_name=None, item_id=None
        ) -> dict:
        result = {}
        iq = None
        try:
            if jid_bare and node_name and item_id:
                iq = await client_xmpp.plugin["xep_0060"].get_item(
                    jid_bare, node_name, item_id, timeout=5)
            elif jid_bare and node_name:
                iq = await client_xmpp.plugin["xep_0060"].get_items(
                    jid_bare, node_name, timeout=15)
            elif jid_bare:
                iq = await client_xmpp.plugin["xep_0060"].get_nodes(
                    jid_bare, timeout=10)
        except (IqError, IqTimeout) as e:
            error_condition = e.iq["error"]["condition"]
            error_text = e.iq["error"]["text"]
        if iq:
            if "pubsub" in iq:
                #if "items" in iq["pubsub"] and "item" in iq["pubsub"]["items"]:
                if iq["pubsub"]["items"]["item"]["payload"] is not None:
                    result = {"content" : str(iq["pubsub"]),
                              "message" : "Success",
                              "error"   : False}
                else:
                    # This is not an error. It is a state of event of an empty node.
                    result = {"content" : None,
                              "message" : "PubSub node appears to be empty",
                              "error"   : True}
            elif "error" in iq:
                result = {"content" : None,
                          "message" : f"{error_condition}: {error_text}",
                          "error"   : True}
            else:
                result = {"content" : None,
                          "message" : f"Unknown error: {str(iq)}",
                          "error"   : True}
        else:
            result = {"content" : None,
                      "message" : "Unknown error: Stanza IQ is empty",
                      "error"   : True}
        return result

if __name__ == "__main__":
    directory_data = (
        os.environ.get("CHA_DATA_DIR") or
        os.path.join(os.environ.get("HOME"), ".local/share/chawan"))
    credentials = os.path.join(directory_data, "credentials.ini")
    config = configparser.ConfigParser()
    config.read(credentials)
    if ("xmpp" in config and
        "address" in config["xmpp"] and
        "password" in config["xmpp"]):
        address = config["xmpp"]["address"]
        password = config["xmpp"]["password"]
        stdin_input = sys.stdin.read()
        if stdin_input:
            uri = stdin_input
        else:
            uri_scheme = os.environ.get("MAPPED_URI_SCHEME")
            uri_path = os.environ.get("MAPPED_URI_PATH")
            uri_query = os.environ.get("MAPPED_URI_QUERY")
            uri = f"{uri_scheme}:{uri_path}?{uri_query}"
        fragmented_uri = urlparse(uri)
        if fragmented_uri.scheme == "xmpp":
            jid_bare = fragmented_uri.path
            item_id = node_name = None
            for parameter in fragmented_uri.query.split(";"):
                if parameter.startswith("node="):
                    node_name = parameter[5:]
                if parameter.startswith("item="):
                    item_id = parameter[5:]
            if jid_bare or jid_bare and node_name:
                client_xmpp = ClientXMPP(address, password)
                client_xmpp.register_plugin("xep_0060")
                #client_xmpp.register_plugin("xep_0199")
                #client_xmpp.connect()
                # ERROR:slixmpp.features.feature_mechanisms.mechanisms:No appropriate login method.
                loop = asyncio.get_event_loop()
                #rtt = loop.run_until_complete(client_xmpp.plugin["xep_0199"].ping())
                #if rtt:
                try:
                    client_xmpp.connect()
                    #result = asyncio.run(
                    #    Xmpp.pubsub(client_xmpp, jid_bare, node_name, item_id))
                    result = loop.run_until_complete(
                        Xmpp.pubsub(client_xmpp, jid_bare, node_name, item_id))
                    client_xmpp.disconnect(
                        ignore_send_queue=False,
                        reason="Chawan: Receiving PubSub data was completed.",
                        wait=2.0)
                    # TODO if no items in result node (an empty node)
                    if result["error"]:
                        message = result["message"]
                        cha_control = f"ConnectionError ConnectionRefused {message}."
                        content = content_type = status_code = None
                    else:
                        """
                        xml = ET.fromstring(result["content"])
                        namespaces = {
                            "atom"   : "http://www.w3.org/2005/Atom",
                            "pubsub" : "http://jabber.org/protocol/pubsub",
                            "xhtml"  : "http://www.w3.org/1999/xhtml"}
                        for namespace in namespaces:
                            ET.register_namespace(
                                namespace, namespaces[namespace])
                        ET.indent(xml, space="  ", level=0)
                        content = ET.tostring(xml, encoding="unicode")
                        """
                        content = result["content"]
                        cha_control = "ControlDone"
                        content_type = "application/pubsub+xml"
                        status_code = "200"
                except Exception as e:
                    message = f"Check whether credentials or XMPP URI are valid; {str(e)}"
                    cha_control = f"ConnectionError ConnectionRefused {message}."
                    content = content_type = status_code = None
            else:
                message = f"Jabber ID or Node Name appear to be missing: {uri}"
                cha_control = f"ConnectionError InvalidURL {message}."
                content = content_type = status_code = None
        else:
            message = f"Invalid XMPP PubSub Query URI: {uri}"
            cha_control = f"ConnectionError InvalidURL {message}."
            content = content_type = status_code = None
    else:
        message = f"XMPP credentials are missing {credentials}"
        cha_control = f"ConnectionError InternalError {message}."
        content = content_type = status_code = None
    Chawan.directives(cha_control, content, content_type, status_code)

Command: printf “xmpp:pubsub.movim.eu?;node=berlin-xmpp-meetup” | python pubsub.py.