fix(image_compare): surface load errors instead of rendering a silent blank#10121
Merged
Conversation
… blank Fixes #10118. mo.image_compare() could render nothing with no error, because the slider derives its height entirely from its images and collapses to ~0px when either fails to load. - frontend: add onError handling that replaces the collapsed slider with a visible error (long data URLs truncated), plus a min-height so it never fully collapses. - python: _process_image_to_url now raises a clear ValueError for a string that is neither an existing file nor a URL, and passes through data:/remote URLs explicitly, instead of swallowing errors into broken data:text/plain URLs or returning invalid srcs as-is. - docs: replace flaky picsum.photos example (fails inside the embed) with a self-contained PIL example (color vs grayscale). - tests: new ImageComparisonComponent.test.tsx (error surfacing + truncation); update test_image_compare.py to assert invalid sources raise and data URLs pass through.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 5 files
Architecture diagram
sequenceDiagram
participant PythonCell as User Python Cell
participant moAPI as mo.image_compare()
participant ImageProcessor as _process_image_to_url()
participant Normalizer as _normalize_image()
participant moData as mo_data.image()
participant Frontend as ImageComparisonComponent (React)
participant Browser as Browser (img load)
Note over PythonCell,Browser: Image Compare improved error handling
PythonCell->>moAPI: invoke(before_image, after_image, ...)
moAPI->>ImageProcessor: process(before_src)
ImageProcessor->>Normalizer: normalize(src)
Normalizer-->>ImageProcessor: normalized (str/Path/bytes/...)
alt valid source (file, BytesIO, bytes)
ImageProcessor->>moData: image(bytes, ext)
moData-->>ImageProcessor: data URL
else str source
alt existing file path
ImageProcessor->>moData: image(read_bytes, ext)
moData-->>ImageProcessor: data URL
else URL or data: prefix
ImageProcessor->>ImageProcessor: validate via urlparse & prefix check
Note over ImageProcessor: NEW: pass through data: and valid remote URLs directly
ImageProcessor-->>moAPI: original src string
else invalid string (neither file nor URL)
ImageProcessor->>ImageProcessor: raise ValueError
Note over ImageProcessor: NEW: fail loud instead of silent broken <img>
ImageProcessor-->>moAPI: exception propagates
moAPI-->>PythonCell: ValueError raised
end
else unsupported type
ImageProcessor->>ImageProcessor: io_to_data_url() or raise
end
moAPI-->>PythonCell: Html with <img> srcs and onError handlers
PythonCell-->>Frontend: renders component with beforeSrc, afterSrc, onError
alt happy path: both images load
Browser->>Browser: load images
Frontend->>Frontend: render slider with minHeight:2rem
Note over Frontend: NEW: minHeight ensures no collapse before load
else image fails to load
Browser-->>Frontend: onError(beforeSrc or afterSrc)
Frontend->>Frontend: setFailedSrcs (React state)
Frontend->>Frontend: render error UI with truncated src
Note over Frontend: NEW: replaces slider with visible error message
Frontend->>Frontend: truncateSrc for long data URLs
end
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes mo.image_compare() cases where the output could collapse to a silent blank by surfacing image-load failures in the frontend and by failing loudly for invalid Python string sources.
Changes:
- Frontend: add
<img onError>handling and enforce a minimum component height; show a visible error message (with truncated long srcs). - Python: make
_process_image_to_urlraiseValueErrorfor string inputs that are neither an existing file path nor a URL; explicitly pass throughdata:and remote URLs. - Docs/tests: update docs example and add/adjust tests to cover error surfacing, truncation, invalid sources raising, and data URL passthrough.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/_plugins/stateless/test_image_compare.py | Updates expectations: invalid string sources now raise; data URLs pass through. |
| marimo/_plugins/stateless/image_compare.py | Tightens string handling to avoid emitting broken <img src=...> values; raises on invalid sources. |
| frontend/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx | Adds load-error UI + min-height to prevent “silent blank” rendering. |
| frontend/src/plugins/impl/image-comparison/tests/ImageComparisonComponent.test.tsx | New tests for error replacement behavior and src truncation. |
| docs/api/media/image_compare.md | Replaces flaky external example with a new embedded example. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- frontend: add a test covering that the load-error state resets when beforeSrc/afterSrc change, so corrected sources aren't stuck behind a stale error banner (reset itself already added in the preceding commit). - python: _normalize_image always returns a handled type (or raises), so the io_to_data_url fallback was dead code. Replace it with a defensive raise and drop the now-unused import.
akshayka
approved these changes
Jul 16, 2026
Contributor
|
🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.23.15-dev25 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #10118. mo.image_compare() could render nothing with no error, because
the slider derives its height entirely from its images and collapses to ~0px
when either fails to load.
visible error (long data URLs truncated), plus a min-height so it never
fully collapses.
that is neither an existing file nor a URL, and passes through data:/remote
URLs explicitly, instead of swallowing errors into broken data:text/plain
URLs or returning invalid srcs as-is.
self-contained PIL example (color vs grayscale).
update test_image_compare.py to assert invalid sources raise and data URLs
pass through.