Skip to content

Subject graph PNG download throws when clicked before the instrument has loaded #1649

Open

Description

@joshunrau

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:44 casts away the null that useInstrument returns while loading:
    const instrument = useInstrument(instrumentId) as AnyUnilingualScalarInstrument;
  • apps/web/src/hooks/useInstrument.ts:13,27 returns null until the bundle is fetched and interpreted, and again if interpretation fails.
  • apps/web/src/routes/_app/datahub/$subjectId/graph.tsx:61 dereferences it inside html2canvas's onclone:
    const formType = instrument.details.title;
  • apps/web/src/routes/_app/datahub/$subjectId/graph.tsx:150 enables the dropdown on instrumentId alone (disabled={!instrumentId}). Line 156 fires the download with void handleGraphDownload().

Reproduce

  1. Open a subject's graph page and throttle the network.
  2. 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

  1. added
    BugType: existing behavior is wrong
    Priority: LowNice to have, cosmetic or speculative
    Difficulty: LowIsolated change, about 2 hours or less
    Area: Webapps/web (clinician-facing React SPA)
    Good First IssueWell-scoped, low-risk and self-contained; a good entry point for a new contributor
    on Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: Webapps/web (clinician-facing React SPA)BugType: existing behavior is wrongDifficulty: LowIsolated change, about 2 hours or lessGood First IssueWell-scoped, low-risk and self-contained; a good entry point for a new contributorPriority: LowNice to have, cosmetic or speculative

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions