A signed-in host cannot view an existing appointment after its meeting type is no longer configured. The detail loader attempts its historical snapshot fallback but returns HTTP 500.
Reproduced against landed main aee8312b54, using an isolated production build and Chromium. This predates the in-progress host duration-choice work.
Steps to reproduce
Configure a meeting type and book an appointment through When.
Remove that meeting type from configuration and reload the configuration.
While signed in as the host, visit the existing appointment's detail URL.
Expected: show the host's historical appointment using its stored snapshot, keeping unavailable meeting-type actions disabled.
Actual: HTTP 500 instead of the detail page.
Confirmed runtime evidence
The reproduction booked a real 30-minute appointment through the authenticated create action. The production writer, not a hand-built fixture, stored this snapshot:
To exercise removal without changing any running configuration, the isolated fixture row's meeting key was changed to an absent key; its real stored snapshot was left untouched. This drives the same missing-config/snapshot-fallback branch. The authenticated GET returned 500 and logged:
TypeError: meeting.additional_duration_minutes is not iterable
at durationsOf
at toPublicEventType
at load
Cause / relevant ownership
apps/web/src/lib/server/appointment/create.ts writes a partial meeting_snapshot: title, actual duration, description, slug.
The detail loader in apps/web/src/routes/(app)/appointment/[id]/+page.server.ts treats parsed snapshot JSON as a complete Meeting.
Projection in appointment/sanitize.ts calls config durationsOf(), which spreads additional_duration_minutes. That property is absent from actual snapshots.
A synthetic full-Meeting snapshot test would mask this failure. Use the actual persisted snapshot shape in the regression test.
Bounded acceptance
Host historical detail renders after type removal using the real partial snapshot shape.
Preserve guest access restrictions and disabled actions for removed meeting types; do not grant new booking/editing authority.
Retain behavior for currently configured meeting types, malformed/missing snapshots and appropriate not-found cases.
Keep snapshot normalization/projection focused; no scheduling-policy or duration-editor expansion is needed.
No live application data, provider/SMTP calls or service restarts were used to reproduce this. Duplicate check covered existing open and closed issues; no matching report found.
## Observed
A signed-in host cannot view an existing appointment after its meeting type is no longer configured. The detail loader attempts its historical snapshot fallback but returns **HTTP 500**.
Reproduced against landed main **aee8312b54a60254282007abaaa3bd6241ecbef6**, using an isolated production build and Chromium. This predates the in-progress host duration-choice work.
## Steps to reproduce
1. Configure a meeting type and book an appointment through When.
2. Remove that meeting type from configuration and reload the configuration.
3. While signed in as the host, visit the existing appointment's detail URL.
Expected: show the host's historical appointment using its stored snapshot, keeping unavailable meeting-type actions disabled.
Actual: HTTP 500 instead of the detail page.
## Confirmed runtime evidence
The reproduction booked a real 30-minute appointment through the authenticated create action. The **production writer**, not a hand-built fixture, stored this snapshot:
```json
{"title":"30-minute chat","duration_minutes":30,"description":"A quick introductory call.","slug":"chat"}
```
To exercise removal without changing any running configuration, the isolated fixture row's meeting key was changed to an absent key; its real stored snapshot was left untouched. This drives the same missing-config/snapshot-fallback branch. The authenticated GET returned 500 and logged:
```text
TypeError: meeting.additional_duration_minutes is not iterable
at durationsOf
at toPublicEventType
at load
```
## Cause / relevant ownership
- apps/web/src/lib/server/appointment/create.ts writes a **partial** meeting_snapshot: title, actual duration, description, slug.
- The detail loader in apps/web/src/routes/(app)/appointment/[id]/+page.server.ts treats parsed snapshot JSON as a complete Meeting.
- Projection in appointment/sanitize.ts calls config durationsOf(), which spreads additional_duration_minutes. That property is absent from actual snapshots.
A synthetic full-Meeting snapshot test would mask this failure. Use the actual persisted snapshot shape in the regression test.
## Bounded acceptance
- Host historical detail renders after type removal using the real partial snapshot shape.
- Preserve guest access restrictions and disabled actions for removed meeting types; do not grant new booking/editing authority.
- Retain behavior for currently configured meeting types, malformed/missing snapshots and appropriate not-found cases.
- Keep snapshot normalization/projection focused; no scheduling-policy or duration-editor expansion is needed.
No live application data, provider/SMTP calls or service restarts were used to reproduce this. Duplicate check covered existing open and closed issues; no matching report found.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Observed
A signed-in host cannot view an existing appointment after its meeting type is no longer configured. The detail loader attempts its historical snapshot fallback but returns HTTP 500.
Reproduced against landed main
aee8312b54, using an isolated production build and Chromium. This predates the in-progress host duration-choice work.Steps to reproduce
Expected: show the host's historical appointment using its stored snapshot, keeping unavailable meeting-type actions disabled.
Actual: HTTP 500 instead of the detail page.
Confirmed runtime evidence
The reproduction booked a real 30-minute appointment through the authenticated create action. The production writer, not a hand-built fixture, stored this snapshot:
To exercise removal without changing any running configuration, the isolated fixture row's meeting key was changed to an absent key; its real stored snapshot was left untouched. This drives the same missing-config/snapshot-fallback branch. The authenticated GET returned 500 and logged:
Cause / relevant ownership
A synthetic full-Meeting snapshot test would mask this failure. Use the actual persisted snapshot shape in the regression test.
Bounded acceptance
No live application data, provider/SMTP calls or service restarts were used to reproduce this. Duplicate check covered existing open and closed issues; no matching report found.