Sharing a calendar event with a community fails on first try, works after reload #4

Closed
opened 2026-07-08 10:43:12 +00:00 by laoc · 3 comments
Owner

Report (user feedback)

Sharing calendar events with a community always fails on the first try; after a reload (or hard reload) it works. The reported error message mentioned something like an "exceeded quota" error (unconfirmed whether related).

To investigate

  • Reproduce: fresh page load → open a calendar event → share with community → expect failure; reload → works.
  • Check whether the failure is a storage quota (QuotaExceededError from localStorage/IndexedDB cache) or a relay/signer state issue on first interaction.
  • Check the share flow's error surface — the user only saw a generic failure.
## Report (user feedback) Sharing calendar events with a community **always fails on the first try**; after a reload (or hard reload) it works. The reported error message mentioned something like an **"exceeded quota"** error (unconfirmed whether related). ## To investigate - Reproduce: fresh page load → open a calendar event → share with community → expect failure; reload → works. - Check whether the failure is a storage quota (`QuotaExceededError` from localStorage/IndexedDB cache) or a relay/signer state issue on first interaction. - Check the share flow's error surface — the user only saw a generic failure.
Author
Owner

Deep investigation done (local e2e stack + a throwaway user against the production relays — all test events deleted afterwards). The plain first-try share flow works for a local-key (nsec) login in both environments, so the report is not a simple "first publish always fails". But the instrumentation surfaced four concrete problems, two of which are unambiguous bugs:

1. Relay rejections are counted as publish successes. relay.publish() resolves {ok:false, message} on rejection, but publish-service.js never checks .ok — every settled publish increments successCount. Captured live: nostr.wine rejected with "restricted: sign up at nostr.wine…" and the app counted it as a success. Consequences: the "all relays failed → remove optimistic event" path is nearly unreachable, the toast overstates reach, and a phantom in-memory repost flips the share row to "Shared" even when nothing landed anywhere.

2. Un-sharing reports "Successfully shared". When a community row is already in shared state, checking it routes Apply to the DELETE path — and the success message still says "Successfully shared with 1 community". Captured live: Apply sent a kind 5 deletion (relay repost count 1→0) while the UI claimed a successful share. A user in this state sees their share vanish, retries in-session without effect, and only after a reload does a genuine create happen — which matches "fails on first try, works after reload" exactly.

3. Relay REQ-budget exhaustion mid-session. A single session produced dozens of NOTICE "ERROR: too many concurrent REQs" on relay.edufeed.org / relay-rpi / nos.lol (max 20 subscriptions per connection). Late-session REQs (share-state detection, relay-list fetches, NIP-46 subscriptions) silently die; a reload gives a fresh socket and budget. Strongest environmental "reload fixes it" mechanism. → split out as its own issue.

4. The "exceeded quota" wording most plausibly comes from a remote NIP-46 signer (nsec.app / Amber bunker), surfaced verbatim — no relay in our homelab stack and no app/dependency code contains any quota string (checked all strfry/khatru write policies and Traefik configs). The share UI displays raw error.message, and NostrConnectSigner rejects with the remote signer's error string as-is. NIP-46 requests also have no timeout: a sleeping bunker on the session's first sign request hangs "Applying changes…" forever; after a reload the bunker is awake and it works. → split out as its own issue.

Question for the reporter: which login method do they use (nsec / browser extension / nsec.app or Amber bunker), and what was the exact error text? That discriminates between (1)/(2) and (4).

Fixing (1) and (2) now on a branch; (3) and (4) filed separately.

Deep investigation done (local e2e stack + a throwaway user against the production relays — all test events deleted afterwards). **The plain first-try share flow works for a local-key (nsec) login in both environments**, so the report is not a simple "first publish always fails". But the instrumentation surfaced four concrete problems, two of which are unambiguous bugs: **1. Relay rejections are counted as publish successes.** `relay.publish()` resolves `{ok:false, message}` on rejection, but `publish-service.js` never checks `.ok` — every settled publish increments `successCount`. Captured live: `nostr.wine` rejected with `"restricted: sign up at nostr.wine…"` and the app counted it as a success. Consequences: the "all relays failed → remove optimistic event" path is nearly unreachable, the toast overstates reach, and a phantom in-memory repost flips the share row to "Shared" even when nothing landed anywhere. **2. Un-sharing reports "Successfully shared".** When a community row is already in shared state, checking it routes Apply to the DELETE path — and the success message still says "Successfully shared with 1 community". Captured live: Apply sent a kind 5 deletion (relay repost count 1→0) while the UI claimed a successful share. A user in this state sees their share vanish, retries in-session without effect, and only after a reload does a genuine create happen — which matches "fails on first try, works after reload" exactly. **3. Relay REQ-budget exhaustion mid-session.** A single session produced dozens of `NOTICE "ERROR: too many concurrent REQs"` on relay.edufeed.org / relay-rpi / nos.lol (max 20 subscriptions per connection). Late-session REQs (share-state detection, relay-list fetches, NIP-46 subscriptions) silently die; a reload gives a fresh socket and budget. Strongest environmental "reload fixes it" mechanism. → split out as its own issue. **4. The "exceeded quota" wording most plausibly comes from a remote NIP-46 signer (nsec.app / Amber bunker), surfaced verbatim** — no relay in our homelab stack and no app/dependency code contains any quota string (checked all strfry/khatru write policies and Traefik configs). The share UI displays raw `error.message`, and `NostrConnectSigner` rejects with the remote signer's error string as-is. NIP-46 requests also have **no timeout**: a sleeping bunker on the session's first sign request hangs "Applying changes…" forever; after a reload the bunker is awake and it works. → split out as its own issue. **Question for the reporter:** which login method do they use (nsec / browser extension / nsec.app or Amber bunker), and what was the exact error text? That discriminates between (1)/(2) and (4). Fixing (1) and (2) now on a branch; (3) and (4) filed separately.
Author
Owner

Fixes for the two confirmed bugs are on branch fix/issue-4-publish-ok-and-share-messaging (relay OK-response checking in both publish paths + honest shared/removed/failed messaging in the share dialog), with unit tests. The environmental mechanisms are tracked in #18 (REQ budget exhaustion) and #19 (NIP-46 timeout + raw signer errors). Leaving this open pending the reporter answer on login method and exact error text.

Fixes for the two confirmed bugs are on branch `fix/issue-4-publish-ok-and-share-messaging` (relay OK-response checking in both publish paths + honest shared/removed/failed messaging in the share dialog), with unit tests. The environmental mechanisms are tracked in #18 (REQ budget exhaustion) and #19 (NIP-46 timeout + raw signer errors). Leaving this open pending the reporter answer on login method and exact error text.
Author
Owner

Confirmed by Steffen. The two client bugs (relay OK handling, share/unshare messaging) are merged to dev; the environmental mechanisms stay tracked in #18 and #19.

Confirmed by Steffen. The two client bugs (relay OK handling, share/unshare messaging) are merged to dev; the environmental mechanisms stay tracked in #18 and #19.
laoc closed this issue 2026-07-09 09:37:02 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
edufeed/edufeed-app#4
No description provided.