~tsileo/microblog.pub#142: 
'Internal Server Error' when opening Stream or Inbox after interacting with misconfigured ActivityPub instance

I'm debugging ActivityPub integration on a service of my own, https://gath.io. The integration is as follows: I follow a Gathio Actor (an event page) from my personal instance, they accept my request, I become RSVPed to that event, I can then send them a public Note to post messages on that event page. If I'm RSVPed and the event is updated, it will send my personal instance a note with the updated information.

When I tried following a Gathio Actor from my microblog.pub instance, the follow request succeeded. I then tried sending them a Note. Then I updated the even. After those operations, trying to open the Stream or Inbox pages on my microblog.pub instance just shows 'Internal Server Error'.

I found the following errors in the database:

In incoming_activity:

Traceback (most recent call last):
  File "/app/app/incoming_activities.py", line 115, in process_next_incoming_activity
    await asyncio.wait_for(
  File "/usr/local/lib/python3.11/asyncio/tasks.py", line 479, in wait_for
    return fut.result()
           ^^^^^^^^^^^^
  File "/app/app/boxes.py", line 2423, in save_to_inbox
    await _handle_create_activity(
  File "/app/app/boxes.py", line 1834, in _handle_create_activity
    wrapped_object = ap.unwrap_activity(create_activity.ap_object)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/app/activitypub.py", line 376, in unwrap_activity
    if get_actor_id(unwrapped_object) != get_actor_id(activity):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/app/activitypub.py", line 313, in get_actor_id
    return get_id(activity["actor"])
                  ~~~~~~~~^^^^^^^^^
KeyError: 'actor'

For the ap_object:

{"@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"], "id": "https://gath.io/gnKsULvN78i7OzUiD_Eyv/m/57eea1bc8e4cf10b62da522a7b22ad84", "type": "Create", "actor": "https://gath.io/gnKsULvN78i7OzUiD_Eyv", "to": ["https://follow.idiot.sh"], "cc": "https://www.w3.org/ns/activitystreams#Public", "object": {"@context": "https://www.w3.org/ns/activitystreams", "id": "https://gath.io/gnKsULvN78i7OzUiD_Eyv/m/71b00701931f8981d002dfd8e924dfcd", "name": "RSVP to Test!", "type": "Note", "cc": "https://www.w3.org/ns/activitystreams#Public", "content": "<p>This event was just updated with new information.</p><ul><li>the start time changed to Monday 15 May 2023 6:12 am</li><li>the end time changed to Monday 15 May 2023 6:50 am</li></ul> See here: <a href=\"https://gath.io/gnKsULvN78i7OzUiD_Eyv\">https://gath.io/gnKsULvN78i7OzUiD_Eyv</a>"}}

And in outgoing_activity:

Traceback (most recent call last):
  File "/opt/venv/.venv/lib/python3.11/site-packages/anyio/streams/tls.py", line 130, in _call_sslobject_method
    result = func(*args)
             ^^^^^^^^^^^
  File "/usr/local/lib/python3.11/ssl.py", line 921, in read
    v = self._sslobj.read(len)
        ^^^^^^^^^^^^^^^^^^^^^^
ssl.SSLWantReadError: The operation did not complete (read) (_ssl.c:2576)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/backends/asyncio.py", line 33, in read
    return await self._stream.receive(max_bytes=max_bytes)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/anyio/streams/tls.py", line 195, in receive
    data = await self._call_sslobject_method(self._ssl_object.read, max_bytes)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/anyio/streams/tls.py", line 137, in _call_sslobject_method
    data = await self.transport_stream.receive()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/anyio/_backends/_asyncio.py", line 1265, in receive
    await self._protocol.read_event.wait()
  File "/usr/local/lib/python3.11/asyncio/locks.py", line 213, in wait
    await fut
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_exceptions.py", line 8, in map_exceptions
    yield
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/backends/asyncio.py", line 31, in read
    with anyio.fail_after(timeout):
  File "/opt/venv/.venv/lib/python3.11/site-packages/anyio/_core/_tasks.py", line 118, in __exit__
    raise TimeoutError
TimeoutError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_transports/default.py", line 60, in map_httpcore_exceptions
    yield
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_transports/default.py", line 353, in handle_async_request
    resp = await self._pool.handle_async_request(req)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_async/connection_pool.py", line 253, in handle_async_request
    raise exc
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_async/connection_pool.py", line 237, in handle_async_request
    response = await connection.handle_async_request(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_async/connection.py", line 90, in handle_async_request
    return await self._connection.handle_async_request(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_async/http11.py", line 105, in handle_async_request
    raise exc
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_async/http11.py", line 84, in handle_async_request
    ) = await self._receive_response_headers(**kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_async/http11.py", line 148, in _receive_response_headers
    event = await self._receive_event(timeout=timeout)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_async/http11.py", line 177, in _receive_event
    data = await self._network_stream.read(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/backends/asyncio.py", line 30, in read
    with map_exceptions(exc_map):
  File "/usr/local/lib/python3.11/contextlib.py", line 155, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
    raise to_exc(exc)
httpcore.ReadTimeout

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/app/app/outgoing_activities.py", line 238, in process_next_outgoing_activity
    resp = await ap.post(next_activity.recipient, payload)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/app/activitypub.py", line 398, in post
    resp = await client.post(
           ^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_client.py", line 1842, in post
    return await self.request(
           ^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_client.py", line 1527, in request
    return await self.send(request, auth=auth, follow_redirects=follow_redirects)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_client.py", line 1614, in send
    response = await self._send_handling_auth(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_client.py", line 1642, in _send_handling_auth
    response = await self._send_handling_redirects(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_client.py", line 1679, in _send_handling_redirects
    response = await self._send_single_request(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_client.py", line 1716, in _send_single_request
    response = await transport.handle_async_request(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_transports/default.py", line 352, in handle_async_request
    with map_httpcore_exceptions():
  File "/usr/local/lib/python3.11/contextlib.py", line 155, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_transports/default.py", line 77, in map_httpcore_exceptions
    raise mapped_exc(message) from exc
httpx.ReadTimeout

And:

Traceback (most recent call last):
  File "/app/app/outgoing_activities.py", line 238, in process_next_outgoing_activity
    resp = await ap.post(next_activity.recipient, payload)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/app/activitypub.py", line 407, in post
    resp.raise_for_status()
  File "/opt/venv/.venv/lib/python3.11/site-packages/httpx/_models.py", line 736, in raise_for_status
    raise HTTPStatusError(message, request=request, response=self)
httpx.HTTPStatusError: Client error '404 Not Found' for url 'https://gath.io/activitypub/inbox'
For more information check: https://httpstatuses.com/404

I don't think /activitypub/inbox is giving a 404, but I'm happy to assume Gathio is misconfigured so am debugging the implementation.

Is there a way to restore my Stream and Inbox pages on my local instance, or to handle these errors less catastrophically?

Status
REPORTED
Submitter
~lown
Assigned to
No-one
Submitted
1 year, 4 months ago
Updated
1 year, 4 months ago
Labels
No labels applied.

~lown 1 year, 4 months ago

I've fixed this by changing get_actor_id() in activitypub.py to:

def get_actor_id(activity: RawObject) -> str:
    if "attributedTo" in activity:
        attributed_to = as_list(activity["attributedTo"])
        return get_id(attributed_to[0])
    else if "actor" in activity:
        return get_id(activity["actor"])
    else:
        return ""

I'm not sure if this is a kosher way to do this or if it creates issues upstream somewhere, though! But at least it gets me my stream and inbox back.

Register here or Log in to comment, or comment via email.