Calendar event naddr links fail to resolve on direct load — relay hints stripped and config not initialized #3

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

Report

This link does not resolve on prod:
https://edufeed.org/calendar/event/naddr1qvzqqqrukvpzqna968zp8c45tcgdgzln2c4twqd9xvfqdc6eey964c8fn07kcmjpqqjxzwpex5ukydrp95ekxepc956r2e3e95unvc3k95mn2wrpxyerzvpnxycxv252m6y

while the same naddr resolves on dev:
https://dev.edufeed.org/calendar/event/naddr1qvzqqqrukvpzqna968zp8c45tcgdgzln2c4twqd9xvfqdc6eey964c8fn07kcmjpqqjxzwpex5ukydrp95ekxepc956r2e3e95unvc3k95mn2wrpxyerzvpnxycxv252m6y

Decoding the naddr shows relays: []no relay hints embedded. Whether it resolves then depends entirely on the deployment's configured relays, which explains the prod/dev difference.

Root cause analysis (confirmed in code)

Three compounding defects:

  1. /calendar/event/[naddr] never initializes the runtime config. src/routes/calendar/event/[naddr]/+page.js calls fetchEventById() directly. The root /[naddr] route (src/routes/[naddr=naddr]/+page.js:18-21) explicitly awaits parent() and calls initializeConfig() first — the calendar route does not. On a cold/direct page load the config is still empty, so getAllLookupRelays() returns [] and a hint-less naddr cannot resolve.

  2. The canonical redirect strips relay hints. The share/copy link points at the root route and does embed relay hints (encodeEventBech32encodeEventToNaddr with seen-relays). But the root route canonically redirects calendar events to /calendar/event/<naddr> via getCanonicalEventRoute(), and src/lib/helpers/eventRouteRedirect.js:77 re-encodes with relays: []. The browser address bar therefore always ends up showing the fragile hint-less URL — which is exactly what users copy.

  3. No staged fallback. fetchEventById (src/lib/helpers/nostrUtils.js:210-250) makes a single addressLoader call with one relay list and gives up after 8 s. There is no "hints failed → configured relays → indexer relays" escalation.

Fix plan

  • Initialize config in the calendar event route load (same pattern as the root naddr route)
  • Preserve relay hints in the canonical redirect (eventRouteRedirect.js)
  • Ensure browser-visible calendar URLs carry relay hints
  • Optional: staged relay fallback in fetchEventById
## Report This link does not resolve on prod: https://edufeed.org/calendar/event/naddr1qvzqqqrukvpzqna968zp8c45tcgdgzln2c4twqd9xvfqdc6eey964c8fn07kcmjpqqjxzwpex5ukydrp95ekxepc956r2e3e95unvc3k95mn2wrpxyerzvpnxycxv252m6y while the same naddr resolves on dev: https://dev.edufeed.org/calendar/event/naddr1qvzqqqrukvpzqna968zp8c45tcgdgzln2c4twqd9xvfqdc6eey964c8fn07kcmjpqqjxzwpex5ukydrp95ekxepc956r2e3e95unvc3k95mn2wrpxyerzvpnxycxv252m6y Decoding the naddr shows `relays: []` — **no relay hints embedded**. Whether it resolves then depends entirely on the deployment's configured relays, which explains the prod/dev difference. ## Root cause analysis (confirmed in code) Three compounding defects: 1. **`/calendar/event/[naddr]` never initializes the runtime config.** `src/routes/calendar/event/[naddr]/+page.js` calls `fetchEventById()` directly. The root `/[naddr]` route (`src/routes/[naddr=naddr]/+page.js:18-21`) explicitly awaits `parent()` and calls `initializeConfig()` first — the calendar route does not. On a cold/direct page load the config is still empty, so `getAllLookupRelays()` returns `[]` and a hint-less naddr **cannot** resolve. 2. **The canonical redirect strips relay hints.** The share/copy link points at the root route and *does* embed relay hints (`encodeEventBech32` → `encodeEventToNaddr` with seen-relays). But the root route canonically redirects calendar events to `/calendar/event/<naddr>` via `getCanonicalEventRoute()`, and `src/lib/helpers/eventRouteRedirect.js:77` re-encodes with `relays: []`. The browser address bar therefore always ends up showing the fragile hint-less URL — which is exactly what users copy. 3. **No staged fallback.** `fetchEventById` (`src/lib/helpers/nostrUtils.js:210-250`) makes a single `addressLoader` call with one relay list and gives up after 8 s. There is no "hints failed → configured relays → indexer relays" escalation. ## Fix plan - [ ] Initialize config in the calendar event route load (same pattern as the root naddr route) - [ ] Preserve relay hints in the canonical redirect (`eventRouteRedirect.js`) - [ ] Ensure browser-visible calendar URLs carry relay hints - [ ] Optional: staged relay fallback in `fetchEventById`
Author
Owner

Fix implemented and verified on branch fix/issue-3-naddr-resolution (2 commits, based on dev).

Changes:

  • /calendar/event/[naddr] load now initializes the runtime config before fetching (same pattern as the root /[naddr] route), so lookup relays are available on cold/direct loads.
  • fetchEventById unions naddr relay hints with the configured lookup relays instead of using hints exclusively (mirrors the existing nevent path).
  • getCanonicalEventRoute re-encodes naddrs with relay hints: seen-relays first, falling back to the hints carried by the incoming naddr (important for cache-served events). The root route passes those inbound hints through the canonical redirect.

Verification (local dev server, empty client cache):

  • Old code + the hint-less naddr from this report → stuck on "Event not found" after the 8s timeout (bug reproduced).
  • Fixed code, same URL cold → event renders fully.
  • Visiting /<naddr-with-hints> now redirects to a /calendar/event/<naddr> URL whose naddr decodes with relays wss://relay-rpi.edufeed.org, wss://relay.edufeed.org — the copied browser URL stays resolvable on any deployment.
  • Garbage naddr → clean "Event not found" page.

Covered by new unit tests (route load config-init, relay union, redirect hint preservation).

Note: the prod/dev difference was config/code drift between deployments — with hint-less naddrs, resolution depended entirely on which relays the deployment queries. After merge+deploy the reported link will still be hint-less, but will resolve via lookup relays, and newly copied links will carry hints.

Fix implemented and verified on branch `fix/issue-3-naddr-resolution` (2 commits, based on `dev`). **Changes:** - `/calendar/event/[naddr]` load now initializes the runtime config before fetching (same pattern as the root `/[naddr]` route), so lookup relays are available on cold/direct loads. - `fetchEventById` unions naddr relay hints with the configured lookup relays instead of using hints exclusively (mirrors the existing nevent path). - `getCanonicalEventRoute` re-encodes naddrs with relay hints: seen-relays first, falling back to the hints carried by the incoming naddr (important for cache-served events). The root route passes those inbound hints through the canonical redirect. **Verification (local dev server, empty client cache):** - Old code + the hint-less naddr from this report → stuck on "Event not found" after the 8s timeout (bug reproduced). - Fixed code, same URL cold → event renders fully. - Visiting `/<naddr-with-hints>` now redirects to a `/calendar/event/<naddr>` URL whose naddr decodes with relays `wss://relay-rpi.edufeed.org`, `wss://relay.edufeed.org` — the copied browser URL stays resolvable on any deployment. - Garbage naddr → clean "Event not found" page. Covered by new unit tests (route load config-init, relay union, redirect hint preservation). Note: the prod/dev difference was config/code drift between deployments — with hint-less naddrs, resolution depended entirely on which relays the deployment queries. After merge+deploy the reported link will still be hint-less, but will resolve via lookup relays, and newly copied links will carry hints.
Author
Owner

Confirmed by Steffen (cold-load resolution + relay hints in the address bar). Merged to dev.

Confirmed by Steffen (cold-load resolution + relay hints in the address bar). Merged to dev.
laoc closed this issue 2026-07-09 09:37:01 +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#3
No description provided.