Repository navigation
Subject graph PNG download throws when clicked before the instrument has loaded #1649
Description
On the subject graph page (/datahub/$subjectId/graph), the Download (PNG) control is enabled as soon as an instrument is selected, but the instrument itself loads asynchronously. If the user clicks Download before the bundle has been fetched and interpreted, handleGraphDownload reads instrument.details.title on null and throws. The handler is fired with void, so the error becomes an unhandled promise rejection: no file is saved and the user sees nothing. The same happens permanently when interpreting the bundle fails, because useInstrument then stays null.
Where
apps/web/src/hooks/useInstrumentVisualization.ts:44casts away thenullthatuseInstrumentreturns while loading:const instrument = useInstrument(instrumentId) as AnyUnilingualScalarInstrument;
apps/web/src/hooks/useInstrument.ts:13,27returnsnulluntil the bundle is fetched and interpreted, and again if interpretation fails.apps/web/src/routes/_app/datahub/$subjectId/graph.tsx:61dereferences it insidehtml2canvas'sonclone:const formType = instrument.details.title;
apps/web/src/routes/_app/datahub/$subjectId/graph.tsx:150enables the dropdown oninstrumentIdalone (disabled={!instrumentId}). Line 156 fires the download withvoid handleGraphDownload().
Reproduce
- Open a subject's graph page and throttle the network.
- Select an instrument, then pick Download → PNG before the instrument bundle has loaded.
Actual: TypeError: Cannot read properties of null (reading 'details') as an unhandled rejection in the console. No file is saved and no notification appears.
Expected: either Download stays disabled until the instrument has loaded, or the download proceeds or reports an error to the user.
Tests
No unit test pins this. A test would have to lock in the crash, or pass a null instrument fixture that the current AnyUnilingualScalarInstrument type rules out. The fix should add a case to apps/web/src/__tests__/datahub-subject-graph.test.tsx with the instrument still loading, asserting that Download is disabled or that no capture is attempted.
Suggested fix
Drop the cast in useInstrumentVisualization so instrument is typed ... | null. Then disable the download (and measure) controls on !instrument rather than !instrumentId, and let the compiler find any other unguarded uses.
Found while raising unit test coverage in #1632.
Activity