[nu-demo] Media seed data writes storage_path with leading slash — '/Photos/foo.jpg' breaks photo/video/song URLs #156

Closed
opened 2026-04-24 02:04:33 +00:00 by mik-tf · 1 comment
Owner

Symptom

In the Photos, Songs, Videos islands on heronu, media was listed by name (so OSIS records existed) but all <img> / <audio> / <video> elements failed to load. Direct curl of the expected webdav URL returned 404.

Root cause

The media seed data (session 13 / homenu seeding) writes photo records with:

storage_path = "/Photos/beach_retreat.jpg"

…leading slash.

In the Photos island, the client-side URL is built as:

// hero_archipelagos/archipelagos/library/photos/src/views/photos_grid.rs:209
let url = format!("{}{}", download_base_url, photo.storage_path);

Where download_base_url already ends with / (because hero_foundry_webdav_client::WebDavClient::files_api_url always adds a trailing slash for the directory form). So the concatenation produces:

/hero_foundry/rpc/api/files/geomind//Photos/beach_retreat.jpg
                                  ^^
                                  DOUBLE SLASH

hero_router's file handler interprets the double-slash as an empty segment and 404s.

Secondary observation

New photos uploaded through the Photos island UI services/mod.rs:73 write:

let storage_path = format!("Photos/{}", filename);

…no leading slash. So new uploads work, only seeded data is broken. This is why the bug was session-13 specific: whoever wrote the initial media seed used a leading slash; the live upload code didn't.

Demo fix applied on heronu (2026-04-24)

Read every photo/song/video record in each seeded context, strip the leading slash from storage_path, write back via {kind}.set. 30 records fixed (9 photos in geomind, 3 in threefold/root/incubaid each, plus 3 each of song + video per context). Verified: curl 'http://10.1.2.2:9988/hero_foundry/rpc/api/files/geomind/Photos/beach_retreat.jpg' now returns 34,206-byte JPEG.

Script: /home/driver/fix_photo_paths.py on heronu (runs via python3 fix_photo_paths.py).

Proper fixes (3 independent)

1. Fix seed data (the real fix)

Wherever media is seeded (hero_osis_media/ scripts, nu-shell service_osis.nu, or a dedicated seed tool) — write paths as Photos/foo.jpg, not /Photos/foo.jpg. Normalize on ingest.

2. Defensive URL construction in photos_grid.rs (belt-and-suspenders)

// hero_archipelagos/archipelagos/library/photos/src/views/photos_grid.rs:209
let url = {
    let base = download_base_url.trim_end_matches('/');
    let path = photo.storage_path.trim_start_matches('/');
    format!("{}/{}", base, path)
};

Same change in Songs (songs_grid.rs) and Videos (videos_grid.rs) — any island that does the same concatenation. This is a pure WASM fix, so it needs a hero_os_app rebuild.

3. Normalize on write in OSIS

The photo.set / song.set / video.set handlers could strip leading slashes from storage_path before persisting. Prevents future seeds from reintroducing the bug.

  • #148 — nu-demo architecture index
  • #139 — hero_foundry not pointed at seed_media (sibling)
  • This supersedes the generic 'Photos don't render' task entry in the internal list.

Verification

After either fix (1), (2), or (3):

# Direct probe
curl -o /dev/null -w '%{http_code}\n' \
  'http://10.1.2.2:9988/hero_foundry/rpc/api/files/geomind/Photos/beach_retreat.jpg'
# → 200 (34206 bytes JPEG)

In the browser, open Photos island in geomind or threefold context → all 9 (or 3) thumbnails should render.

Signed-off-by: mik-tf

## Symptom In the Photos, Songs, Videos islands on heronu, media was listed by name (so OSIS records existed) but all `<img>` / `<audio>` / `<video>` elements failed to load. Direct `curl` of the expected webdav URL returned 404. ## Root cause The **media seed data** (session 13 / homenu seeding) writes photo records with: ```toml storage_path = "/Photos/beach_retreat.jpg" ``` …leading slash. In the Photos island, the client-side URL is built as: ```rust // hero_archipelagos/archipelagos/library/photos/src/views/photos_grid.rs:209 let url = format!("{}{}", download_base_url, photo.storage_path); ``` Where `download_base_url` already ends with `/` (because `hero_foundry_webdav_client::WebDavClient::files_api_url` always adds a trailing slash for the directory form). So the concatenation produces: ``` /hero_foundry/rpc/api/files/geomind//Photos/beach_retreat.jpg ^^ DOUBLE SLASH ``` hero_router's file handler interprets the double-slash as an empty segment and 404s. ## Secondary observation New photos uploaded through the Photos island UI `services/mod.rs:73` write: ```rust let storage_path = format!("Photos/{}", filename); ``` …no leading slash. So **new uploads work, only seeded data is broken**. This is why the bug was session-13 specific: whoever wrote the initial media seed used a leading slash; the live upload code didn't. ## Demo fix applied on heronu (2026-04-24) Read every `photo`/`song`/`video` record in each seeded context, strip the leading slash from `storage_path`, write back via `{kind}.set`. 30 records fixed (9 photos in geomind, 3 in threefold/root/incubaid each, plus 3 each of song + video per context). Verified: `curl 'http://10.1.2.2:9988/hero_foundry/rpc/api/files/geomind/Photos/beach_retreat.jpg'` now returns 34,206-byte JPEG. Script: `/home/driver/fix_photo_paths.py` on heronu (runs via `python3 fix_photo_paths.py`). ## Proper fixes (3 independent) ### 1. Fix seed data (the real fix) Wherever media is seeded (`hero_osis_media/` scripts, nu-shell `service_osis.nu`, or a dedicated seed tool) — write paths as `Photos/foo.jpg`, not `/Photos/foo.jpg`. Normalize on ingest. ### 2. Defensive URL construction in photos_grid.rs (belt-and-suspenders) ```rust // hero_archipelagos/archipelagos/library/photos/src/views/photos_grid.rs:209 let url = { let base = download_base_url.trim_end_matches('/'); let path = photo.storage_path.trim_start_matches('/'); format!("{}/{}", base, path) }; ``` Same change in Songs (songs_grid.rs) and Videos (videos_grid.rs) — any island that does the same concatenation. This is a pure WASM fix, so it needs a hero_os_app rebuild. ### 3. Normalize on write in OSIS The `photo.set` / `song.set` / `video.set` handlers could strip leading slashes from `storage_path` before persisting. Prevents future seeds from reintroducing the bug. ## Related - https://forge.ourworld.tf/lhumina_code/home/issues/148 — nu-demo architecture index - https://forge.ourworld.tf/lhumina_code/home/issues/139 — hero_foundry not pointed at seed_media (sibling) - This supersedes the generic 'Photos don't render' task entry in the internal list. ## Verification After either fix (1), (2), or (3): ```bash # Direct probe curl -o /dev/null -w '%{http_code}\n' \ 'http://10.1.2.2:9988/hero_foundry/rpc/api/files/geomind/Photos/beach_retreat.jpg' # → 200 (34206 bytes JPEG) ``` In the browser, open Photos island in `geomind` or `threefold` context → all 9 (or 3) thumbnails should render. Signed-off-by: mik-tf
Author
Owner

Moved to hero_demo#24 — see lhumina_code/hero_demo#24

Moved to hero_demo#24 — see https://forge.ourworld.tf/lhumina_code/hero_demo/issues/24
Sign in to join this conversation.
No labels
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
lhumina_code/home#156
No description provided.