Skip to content

fix(image_compare): surface load errors instead of rendering a silent blank#10121

Merged
akshayka merged 3 commits into
mainfrom
ms/fix/marimo-file-not-recognized
Jul 16, 2026
Merged

fix(image_compare): surface load errors instead of rendering a silent blank#10121
akshayka merged 3 commits into
mainfrom
ms/fix/marimo-file-not-recognized

Conversation

@mscolnick

Copy link
Copy Markdown
Contributor

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.

… 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.
Copilot AI review requested due to automatic review settings July 9, 2026 16:53
@mscolnick
mscolnick requested a review from akshayka as a code owner July 9, 2026 16:53
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Jul 10, 2026 5:06pm

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread marimo/_plugins/stateless/image_compare.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_url raise ValueError for string inputs that are neither an existing file path nor a URL; explicitly pass through data: 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.

Comment thread frontend/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx Outdated
Comment thread docs/api/media/image_compare.md
@mscolnick mscolnick added the bug Something isn't working label Jul 9, 2026
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
akshayka merged commit 56bd6af into main Jul 16, 2026
44 checks passed
@akshayka
akshayka deleted the ms/fix/marimo-file-not-recognized branch July 16, 2026 16:35
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.23.15-dev25

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

Labels

bug Something isn't working documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

marimo.image_compare output nothing

3 participants