Skip to content

fix(mpl): contain comm callback errors in mpl_interactive#9532

Merged
kirangadhave merged 2 commits into
mainfrom
kg/mpl-callback-exceptions
May 13, 2026
Merged

fix(mpl): contain comm callback errors in mpl_interactive#9532
kirangadhave merged 2 commits into
mainfrom
kg/mpl-callback-exceptions

Conversation

@kirangadhave
Copy link
Copy Markdown
Member

Summary

A raising callback inside mpl_interactive._handle_comm_msg (e.g. matplotlib's AttributeError: 'Axes' object has no attribute '_pan_start' from end_pan without a prior start_pan) was propagating up through MarimoComm.handle_msgWIDGET_COMM_MANAGER.receive_comm_message → the kernel's request handler, terminating asyncio.run and killing the kernel subprocess. The uvicorn parent kept serving so the UI just reported "stopped responding".

This wraps the handle_json and _handle_download calls in try/except Exception and logs via LOGGER.exception so a buggy callback is contained while the traceback still surfaces for diagnosis. BaseException is intentionally not caught.

Fixes the kernel-crash half of the matplotlib pan/zoom issue (see linked Linear issue). The underlying matplotlib _pan_start bug is tracked separately.

Test plan

  • Manual repro via the linked Linear repro (pan → re-run cell → zoom → pan): exception logged, kernel stays alive, figure remains responsive.
  • Direct programmatic injection: _handle_comm_msg with a raising handle_json returns cleanly and a follow-up message is processed.

A raising callback in _handle_comm_msg or _handle_download was killing the
kernel subprocess via asyncio.run. Catch and log instead.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 12, 2026

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

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment May 12, 2026 10:40pm

Request Review

@kirangadhave kirangadhave added the bug Something isn't working label May 12, 2026
@kirangadhave kirangadhave marked this pull request as ready for review May 12, 2026 22:39
@kirangadhave kirangadhave enabled auto-merge (squash) May 12, 2026 22:41
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

No issues found across 1 file

Architecture diagram
sequenceDiagram
    participant UI as Browser UI
    participant UV as Uvicorn Server
    participant KRN as Kernel Subprocess
    participant CM as WIDGET_COMM_MANAGER
    participant MC as MarimoComm
    participant MPI as mpl_interactive
    participant FM as Figure Manager
    participant LOG as Logger

    Note over UI,LOG: Matplotlib Pan/Zoom Event Flow

    UI->>UV: Comm message (pan/zoom event)
    UV->>KRN: receive_comm_message()
    KRN->>CM: handle message
    CM->>MC: handle_msg()
    MC->>MPI: _handle_comm_msg()

    alt Event type is "download"
        MPI->>MPI: _handle_download(fmt)
        alt Download succeeds
            MPI->>FM: savefig()
            MPI->>UI: Send blob via comm
        else Exception in download
            MPI->>LOG: LOGGER.exception()
            MPI->>MPI: Return cleanly
        end
    else Event type is JSON (mouse/toolbar)
        MPI->>FM: handle_json(event)
        alt Callback succeeds
            FM-->>MPI: void
            MPI->>UI: Updated figure state
        else Exception propagates
            FM-->>MPI: raise Exception
            Note over MPI,LOG: CHANGED: Exception caught here
            MPI->>LOG: LOGGER.exception()
            MPI->>MPI: Continue processing
        end
    end

    alt Exception not caught (before fix)
        MPI->>KRN: Unhandled exception propagates
        KRN->>KRN: asyncio.run terminates
        KRN-->>UV: Subprocess dies
        UV->>UI: "stopped responding"
    else Exception caught (after fix)
        KRN->>KRN: Remains alive
        KRN-->>UI: Normal response continues
    end

    Note over UI,LOG: Error handling boundary: all exceptions from FM callbacks<br/>are contained within mpl_interactive layer
Loading

@Light2Dark Light2Dark requested a review from Copilot May 13, 2026 00:03
Copy link
Copy Markdown
Collaborator

@Light2Dark Light2Dark left a comment

Choose a reason for hiding this comment

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

should we add tests?

@kirangadhave kirangadhave merged commit 502af73 into main May 13, 2026
45 checks passed
@kirangadhave kirangadhave deleted the kg/mpl-callback-exceptions branch May 13, 2026 00:03
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR prevents exceptions raised inside matplotlib interactive comm callbacks from propagating through the comm manager and crashing the kernel subprocess, while still emitting tracebacks for debugging.

Changes:

  • Wrap self._figure_manager.handle_json(event) in try/except Exception and log failures with LOGGER.exception.
  • Wrap figure download rendering/sending logic in try/except Exception and log failures with LOGGER.exception.

@github-actions
Copy link
Copy Markdown

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

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants