Skip to content

fix(media-library): surface parse error in VideoPreview instead of infinite loading#12155

Draft
sjelfull wants to merge 2 commits intomainfrom
fix/video-input-loading-bug
Draft

fix(media-library): surface parse error in VideoPreview instead of infinite loading#12155
sjelfull wants to merge 2 commits intomainfrom
fix/video-input-loading-bug

Conversation

@sjelfull
Copy link
Member

Problem

When getMediaLibraryId() throws (e.g. library ID doesn't start with ml), the catch block returns null, causing useVideoPlaybackInfo(null) to return an empty state — not loading, not error, no result. The render logic then falls through to <VideoSkeleton /> with no error prop, showing an infinite loading skeleton with no way to recover.

Fix

Return the parse error from the useMemo as a tuple [params, error] and render <VideoSkeleton error={parseError} /> when present. This shows the critical-tone skeleton immediately instead of loading forever.

Changes

  • VideoPreview.tsx: videoPlaybackParams memo now returns [params, parseError] tuple. Parse error check added before playback info state checks in render.
  • VideoPreview.test.ts: 6 unit tests for getMediaLibraryId parse logic (valid refs, invalid prefix, empty strings, missing parts).

Follow-up

VideoSkeleton currently shows critical tone + stops animation on error, but doesn't display error message text or a retry button. A follow-up commit will enhance the skeleton UX.

Testing

  • npx vitest run src/media-library/plugin/VideoInput/__tests__/VideoPreview.test.ts — 6/6 green
  • npx tsc --noEmit — no new type errors

…finite loading

When getMediaLibraryId() throws (e.g. library ID doesn't start with 'ml'),
the catch block returned null, causing useVideoPlaybackInfo(null) to return
an empty state — not loading, not error, no result. The render logic then
fell through to <VideoSkeleton /> with no error, showing an infinite
loading skeleton.

Fix: return the parse error from the useMemo as a tuple [params, error]
and render <VideoSkeleton error={parseError} /> when it's present. This
shows the critical tone skeleton immediately instead of loading forever.

- Export getMediaLibraryId for direct unit testing
- Add 6 unit tests for getMediaLibraryId parse logic

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Feb 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
page-building-studio Ready Ready Preview, Comment Feb 13, 2026 0:13am
test-studio Ready Ready Preview, Comment Feb 13, 2026 0:13am
3 Skipped Deployments
Project Deployment Actions Updated (UTC)
e2e-studio Ignored Ignored Feb 13, 2026 0:13am
studio-workshop Ignored Ignored Preview Feb 13, 2026 0:13am
test-next-studio Ignored Ignored Feb 13, 2026 0:13am

Request Review

@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

🧪 E2E Preview environment

🔑 Environment Variables for Local Testing

This is the preview URL for the E2E tests: https://e2e-studio-h6v7qgta9.sanity.dev

To run the E2E tests locally, you can use the following environment variables, then run pnpm test:e2e --ui to open the Playwright test runner.

💬 Remember to build the project first with pnpm build:e2e.

  SANITY_E2E_PROJECT_ID=ittbm412
  SANITY_E2E_BASE_URL=https://e2e-studio-h6v7qgta9.sanity.dev
  SANITY_E2E_DATASET="update depending the project you want to test (pr-12155-chromium-21986313723 || pr-12155-firefox-21986313723 )"
  SANITY_E2E_DATASET_CHROMIUM=pr-12155-chromium-21986313723
  SANITY_E2E_DATASET_FIREFOX=pr-12155-firefox-21986313723

@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

📊 Playwright Test Report

Download Full E2E Report

This report contains test results, including videos of failing tests.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

📚 TypeDoc Generation Result

TypeDoc generated successfully!

  • File size: 8.0M
  • Total exports: 1049
  • Artifact: sanity-typedoc-a3c6bf529d12fae1443b96d729b838fa7a77195b

The TypeDoc JSON file has been generated and validated. All documentation scripts completed successfully.

VideoSkeleton accepted an error prop but displayed no message — users
saw a red static skeleton with no indication of what went wrong.

Changes:
- Add error message text below skeleton when error prop is set
- Add retry prop (optional callback) with ghost Retry button
- Wire playbackInfoState.retry through VideoPreview for transient
  errors (network failures, timeouts)
- Parse errors (deterministic) intentionally omit retry — no point
  retrying a malformed asset reference

Follows InvalidVideoWarning pattern: Card tone + Text + Button from
ui-components.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

⚡️ Editor Performance Report

Updated Fri, 13 Feb 2026 12:20:10 GMT

Benchmark reference
latency of sanity@latest
experiment
latency of this branch
Δ (%)
latency difference
article (title) 28.2 efps (36ms) 32.8 efps (31ms) -5ms (-14.1%)
article (body) 39.0 efps (26ms) 42.1 efps (24ms) -2ms (-7.4%)
article (string inside object) 33.9 efps (30ms) 38.5 efps (26ms) -4ms (-11.9%)
article (string inside array) 32.3 efps (31ms) 39.2 efps (26ms) -6ms (-17.7%)
recipe (name) 90.9 efps (11ms) 90.9 efps (11ms) +0ms (-/-%)
recipe (description) 45.5 efps (22ms) 47.6 efps (21ms) -1ms (-4.5%)
recipe (instructions) 99.9+ efps (9ms) 99.9+ efps (10ms) +1ms (-/-%)
singleString (stringField) 99.9+ efps (8ms) 99.9+ efps (8ms) +1ms (-/-%)
synthetic (title) 44.4 efps (23ms) 47.6 efps (21ms) -2ms (-6.7%)
synthetic (string inside object) 47.6 efps (21ms) 50.0 efps (20ms) -1ms (-4.8%)

efps — editor "frames per second". The number of updates assumed to be possible within a second.

Derived from input latency. efps = 1000 / input_latency

Detailed information

🏠 Reference result

The performance result of sanity@latest

Benchmark latency p75 p90 p99 blocking time test duration
article (title) 36ms 40ms 51ms 81ms 53ms 8.1s
article (body) 26ms 32ms 52ms 121ms 293ms 6.2s
article (string inside object) 30ms 35ms 52ms 79ms 1ms 7.3s
article (string inside array) 31ms 36ms 52ms 94ms 79ms 7.6s
recipe (name) 11ms 15ms 17ms 45ms 0ms 5.5s
recipe (description) 22ms 24ms 26ms 42ms 0ms 4.7s
recipe (instructions) 9ms 11ms 12ms 34ms 0ms 3.2s
singleString (stringField) 8ms 10ms 12ms 23ms 0ms 4.6s
synthetic (title) 23ms 26ms 78ms 102ms 1474ms 9.8s
synthetic (string inside object) 21ms 27ms 76ms 148ms 1417ms 9.5s

🧪 Experiment result

The performance result of this branch

Benchmark latency p75 p90 p99 blocking time test duration
article (title) 31ms 40ms 49ms 83ms 38ms 8.2s
article (body) 24ms 27ms 41ms 96ms 269ms 6.2s
article (string inside object) 26ms 31ms 55ms 67ms 31ms 7.0s
article (string inside array) 26ms 29ms 37ms 66ms 10ms 7.1s
recipe (name) 11ms 14ms 16ms 41ms 0ms 5.3s
recipe (description) 21ms 24ms 27ms 50ms 0ms 4.6s
recipe (instructions) 10ms 11ms 12ms 13ms 0ms 3.2s
singleString (stringField) 8ms 10ms 14ms 31ms 0ms 4.8s
synthetic (title) 21ms 27ms 81ms 106ms 1280ms 9.6s
synthetic (string inside object) 20ms 23ms 45ms 114ms 1109ms 9.3s

📚 Glossary

column definitions

  • benchmark — the name of the test, e.g. "article", followed by the label of the field being measured, e.g. "(title)".
  • latency — the time between when a key was pressed and when it was rendered. derived from a set of samples. the median (p50) is shown to show the most common latency.
  • p75 — the 75th percentile of the input latency in the test run. 75% of the sampled inputs in this benchmark were processed faster than this value. this provides insight into the upper range of typical performance.
  • p90 — the 90th percentile of the input latency in the test run. 90% of the sampled inputs were faster than this. this metric helps identify slower interactions that occurred less frequently during the benchmark.
  • p99 — the 99th percentile of the input latency in the test run. only 1% of sampled inputs were slower than this. this represents the worst-case scenarios encountered during the benchmark, useful for identifying potential performance outliers.
  • blocking time — the total time during which the main thread was blocked, preventing user input and UI updates. this metric helps identify performance bottlenecks that may cause the interface to feel unresponsive.
  • test duration — how long the test run took to complete.

@github-actions
Copy link
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 31.02% 17634 / 56838
🔵 Statements 27.53% 21984 / 79835
🔵 Functions 30.28% 3359 / 11093
🔵 Branches 20.72% 14198 / 68519
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/sanity/src/media-library/plugin/VideoInput/VideoPreview.tsx 2.7% 3.12% 12.5% 4.49% 28-85
packages/sanity/src/media-library/plugin/VideoInput/VideoSkeleton.tsx 0% 0% 0% 0% 11-13
Generated in workflow #52000 for commit 0a3603b by the Vitest Coverage Report Action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant