iOS PWA: Save Edit stuck in Saving, composer inaccessible and dictated text lost

AI-generated summary

Ethsim2 reported an intermittent bug on the iOS PWA where the composer became stuck in a Saving state after editing a post, preventing access to unsaved dictated text. The issue occurred on an iPhone 16 Pro running iOS 27.0.1 with a self-hosted Discourse instance behind Caddy (HTTP/3). Server logs indicated that while drafts and uploads were saved successfully, the final post-update request did not reach the Rails controller before the user manually switched from Wi-Fi to cellular, resulting in data loss.

In a follow-up update, Ethsim2 described additional connectivity issues on iOS 27.2, including stalled topic operations and significantly delayed loading of the main JavaScript bundle (taking over 30 seconds instead of under one second). Logs showed incomplete HTTP/2 responses and connection resets by peer, though it remains unclear whether these were initiated by the client or network infrastructure. The user questions whether the composer is designed to preserve or allow recovery of unsaved changes when a save request stalls, noting that previous related reports had different causes.

I encountered an intermittent issue while editing an existing post in my self-hosted Discourse instance on 21 October 2026. The composer became stuck in its Saving state, and I couldn’t return to the editor to recover some dictated text.

I have since examined the Caddy and nginx access logs and Discourse’s post revision history.

Environment

  • Client: iPhone 16 Pro, Safari Home Screen PWA

  • iOS: 27.0.1

  • Discourse: 2026.10.0-latest +406 commits, as shown in the admin dashboard later that day (162 newer changes available)

  • Hosting: self-hosted, private study archive

  • Reverse proxy: Caddy v2.11.4, providing HTTP/3 over QUIC

  • Backend: Discourse nginx behind Caddy using a Unix socket

  • Network: university Wi-Fi initially, followed by EE cellular

What happened

I was editing a post containing an image of a physics lecture slide.

I dictated additional mathematical notes, including fractions, underneath the image and then quickly pressed Save Edit.

The blue horizontal Saving bar remained visible at the bottom of the screen and did not complete.

I tried touching the Saving bar, but this did not reopen the composer. As a result, I couldn’t select or copy the unsaved text elsewhere.

I waited longer than I normally would.

Only after the Saving operation was already stuck did I manually disable Wi-Fi, hoping that switching to cellular would allow the request to complete.

The interface did not immediately recover. I also experienced buffering when trying to navigate using the site logo.

When I could edit the post again, the dictated fractions were missing.

Server-side investigation

The relevant time was approximately 12:20 BST on 21 October 2026.

My Caddy logs show:

Time (BST) Request Result
12:19:39 POST /drafts.json 200
12:19:40 POST /uploads.json 200
12:19:44 POST /drafts.json 200
12:20:08 PUT /posts/70695 Caddy status 0
12:20:55 PUT /posts/70695 200

The unsuccessful PUT used HTTP/3. Caddy recorded a duration of approximately 110 ms, while nginx recorded an HTTP 400 response with no Discourse post-update controller execution.

Numerous other requests originating from the cellular connection also received Caddy status 0 at approximately the same time.

Caddy itself did not restart. Docker reports zero restarts since 15 October, and the operational logs contain no corresponding reload or shutdown event.

Draft recovery

There were successful draft-save requests immediately before the incident.

However, I remember the earlier contents as the slide image without the additional dictated text. I entered the fractions afterwards and pressed Save Edit shortly thereafter.

Therefore, I cannot establish that the missing dictation was included in either successful autosave.

When I subsequently inspected the post revisions, the successful revision at 12:20:55 contained the image but not the dictated fractions.

I also checked the current draft records, but neither the old nor the new topic draft key had a remaining draft at the time of inspection.

Expected behaviour

If an edit request becomes stuck or is interrupted, I would expect the composer to preserve its unsaved contents and provide a way to retry, cancel or return to editing.

In particular, the interface should ideally not make unsaved text inaccessible indefinitely while showing Saving.

Actual behaviour

The composer remained inaccessible, touching the Saving bar did not reopen it, and the dictated text was no longer available when editing resumed.

Questions

  1. Is the composer expected to remain inaccessible indefinitely while an edit request is outstanding?

  2. Is there a timeout or recovery mechanism intended to restore editing when a network request is interrupted?

  3. Should an interrupted Save Edit operation preserve the in-memory text or draft contents even if the request never reaches the Rails post-update controller?

  4. Would any particular client-side logging or instrumentation be useful if this happens again on iOS?

I appreciate that the network change may explain the eventual request cancellations. However, the Saving interface had already become stuck before I manually changed networks.

I have not established whether the initial delay originated in Discourse’s JavaScript, iOS/WebKit networking or the university connection.

Related discussions

I have an existing MPTCP / iOS connection-continuity discussion, where I described this same incident from the transport perspective.

I also previously reported edited posts occasionally remaining stale in DiscourseHub on iOS. In that separate issue, edits had successfully reached the server, but the already-rendered post did not update until a refresh. Another user reported noticing that behaviour too.

I do not know whether the two issues share a cause. The current incident is different because the initial post-edit request was not processed successfully.

I also found two earlier reports involving a composer stuck in Saving:

Both had different identified causes, and I am not assuming they explain this incident.

I have attached a ZIP discourse_ios_save_evidence_2026-10-21_domain_redacted.zip (6.3 KB) containing selected, redacted Caddy/nginx diagnostic extracts, revision information and the chronology described above.

I would appreciate any advice on how the composer is intended to recover from a stalled request, particularly when unsaved changes cannot be copied before a network interruption.

A further update following some iOS PWA problems on 28 October 2026, now on iOS 27.2 (iPhone 16 Pro).

These were not exact reproductions of the original lost-dictation problem, but I have checked the Caddy and nginx logs to understand what happened.

10:58 GMT — topic operation stalled

While leaving the library, a topic operation appeared to become stuck in the interface.

Caddy recorded two HTTP/3 requests to POST /t/13515/merge-topic:

  • 10:58:16: status 0, duration approximately 0.15 ms.
  • 10:58:41: HTTP 200, duration approximately 595 ms.

The successful request also appears in nginx as topics/merge_topic, HTTP 200.

This confirms that a later request was processed successfully, but does not establish why the earlier request ended without a completed response.

12:26 GMT — PWA loading problems

While in a lecture theatre, I was unable to load the PWA normally.

Caddy recorded four HTTP/3 requests for the main Discourse JavaScript bundle, completing between 12:27:05 and 12:27:42.

All returned HTTP 200 and logged 627,219 response bytes, but their durations were approximately 31.4, 27.1, 29.4 and 17.3 seconds.

The same resource normally completed in under a second, both before and after this interval.

12:42 GMT — further PWA loading problem

Another HTTP/3 request for the same JavaScript bundle took approximately 24.3 seconds.

At 12:42:41, Caddy also logged an incomplete HTTP/2 reverse-proxy response:

aborting with incomplete response
writing: write tcp ...: connection reset by peer

The upstream was the existing Unix socket to nginx. The error occurred while Caddy was writing towards the client-facing TCP connection, rather than being an identified Unix-socket failure.

The logs cannot establish whether the reset was initiated by iOS or by network infrastructure between the client and VPS.

I did not manually change the iPhone’s network settings during the two lecture-theatre incidents.

Relevance to the original report

I appreciate that these loading and topic-operation problems may have a different cause from the original Save Edit issue.

However, they demonstrate that the iOS PWA has encountered substantial request delays and an interrupted response in circumstances where I rely on it for editing notes.

My main question remains whether the composer is expected to preserve and make unsaved text accessible when a Save Edit request stalls, rather than leaving it inaccessible behind the Saving state.

I would be grateful for any guidance on useful client-side diagnostics or intended composer recovery behaviour.