Guard blob viewer computeds against missing blob

What does this MR do and why?

Addresses the sentry TypeError - "Cannot read properties of undefined (reading 'renderError')". GraphQL query resolves without a blob (deleted file, stale URL, or crawler traffic), leaving the viewer computed undefined while downstream code reads its properties without any guard.

This MR does a few things:

  • adds null guards around those reads and skips viewer initialisation when no blob is returned, which also eliminates a second endsWith TypeError in the highlight-worker setup path
  • the template condition is tightened so a missing blob no longer crashes; instead of leaving the file section blank, it renders a GlEmptyState where the file would be (same pattern work items use for a resolved-but-empty query):
    • query resolves with no blob → "File not found" with a Browse files link to the repository root
    • blob resolves but carries no viewers → "Unable to display file" with a Reload page button, since this state may be transient
  • A blob that resolves but carries no viewers — a schema violation because simpleViewer is non-nullable — is reported to Sentry at info level to surface unexpected data anomalies

References

Sentry report: https://new-sentry.gitlab.net/organizations/gitlab/issues/3967899/?project=4

Screenshots or screen recordings

Blob page (/flightjs/Flight/-/blob/master/README.md) when the getBlobInfo query resolves with no blob (Playwright route mock):

Before After
blob_viewer_before_console blob_viewer_file_not_found
Stuck loading spinner; two TypeErrors: Cannot read properties of undefined (reading 'endsWith') and (reading 'renderError') "File not found" empty state with a Browse files link; no console errors

Blob that resolves without viewers (route mock nulling simpleViewer/richViewer in the getBlobInfo and getBlobControls responses) — shows the reload variant, and the info-level Sentry report fires:

Screenshot

blob_viewer_no_viewers

Normal blob page with this fix applied (unmocked response) — renders as before, no console errors:

Screenshot

blob_viewer_normal

How to set up and validate locally

  1. Open any file in the repository blob view, for example /<project>/-/blob/master/README.md, and confirm the page renders as before with no console errors.

  2. To simulate the crash scenario, intercept the getBlobInfo GraphQL response (browser DevTools request override, or a Playwright route mock) and make it resolve with no blob:

    { "data": { "isBinary": false, "project": { "id": "gid://gitlab/Project/1", "repository": { "empty": false, "blobs": { "nodes": [] } } } } }
  3. Reload the blob page. Before this change, the console shows two TypeErrors (reading 'renderError' and reading 'endsWith') and a broken file view; after this change, there are no console errors and a "File not found" empty state renders in the file section, with a Browse files link back to the repository root.

  4. To see the second empty-state variant, intercept the real getBlobInfo and getBlobControls responses and set simpleViewer and richViewer to null on the blob node (both queries write the same blob to the Apollo cache, so both must be mocked). Reload: the file section shows "Unable to display file" with a Reload page button, and an info-level message is reported to Sentry.

Edited by Chaoyue Zhao

Merge request reports

Loading
Loading