Skip to content

fix(lazy): return value takes precedence over imperative output in mo.lazy - #10128

Draft
SarthakB11 wants to merge 1 commit into
marimo-team:mainfrom
SarthakB11:fix/lazy-output-precedence-9540
Draft

fix(lazy): return value takes precedence over imperative output in mo.lazy#10128
SarthakB11 wants to merge 1 commit into
marimo-team:mainfrom
SarthakB11:fix/lazy-output-precedence-9540

Conversation

@SarthakB11

Copy link
Copy Markdown

This pull request was authored by a coding agent.

What

A callable passed to mo.lazy that both writes imperative output (mo.output.append/replace) and returns a value now shows the returned value, matching the display you get from a normal cell.

Why

mo.lazy's load function runs under the owning cell's execution context. Imperative mo.output calls inside the deferred callable broadcast to that cell and overwrite its output, which hides the lazy widget. So the notebook from #9540 showed 'a' instead of the table:

def _():
    mo.output.append('a')
    return mo.ui.table(
        data=[
            {"first_name": "Michael", "last_name": "Scott"},
            {"first_name": "Dwight", "last_name": "Schrute"},
        ],
        label="Users",
    )
mo.lazy(_)

Fixes #9540.

How

_load now runs the deferred callable with its imperative output isolated into a throwaway CellOutputList, and drops those broadcasts so they no longer overwrite the owning cell. It then reconciles the result: the returned value wins, and the accumulated imperative output is used only when the callable returns nothing. This is the same precedence a cell applies to its last expression versus its mo.output calls.

Tests

Two tests in tests/_plugins/stateless/test_lazy.py, both driven through the full function_call_request RPC path (which installs the owning cell's execution context, the condition that surfaces the bug):

  • test_lazy_return_value_takes_precedence_over_append: a callable that appends and returns shows the returned value, and the append no longer leaks into the owning cell's output.
  • test_lazy_falls_back_to_appended_output_when_no_return: a callable that only appends still renders that output inside the widget.

Both fail on main and pass with this change. make py-check is clean (ruff and mypy).

A deferred render passed to mo.lazy runs under the owning cell's
execution context, so imperative mo.output.append/replace calls inside
it broadcast to and overwrite that cell's output, hiding the lazy
widget. A callable that both appended and returned a value therefore
showed the appended content instead of the returned one.

Isolate the deferred callable's imperative output into a throwaway
CellOutputList and drop its broadcasts, then reconcile: the returned
value wins, falling back to the accumulated imperative output only when
the callable returns nothing. This mirrors how a cell reconciles its
last expression with mo.output calls.

Fixes marimo-team#9540

Signed-off-by: SarthakB11 <sarthak.bhardwaj21b@iiitg.ac.in>
@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 9, 2026 8:11pm

Request Review

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@Bartok9

Bartok9 commented Jul 15, 2026

Copy link
Copy Markdown

Thanks @SarthakB11 for the solid fix and tests here.

I rebased this work onto current main and opened a salvage PR with CLA signed from my side so it can clear the CLA gate:

#10195

Full credit remains with you (Co-authored-by + salvage note). Happy to close #10195 in favor of this PR if you prefer to sign CLA on #10128 instead — either path is fine.

@SarthakB11

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@SarthakB11

Copy link
Copy Markdown
Author

@dmadisetti CLA is showing signed and all checks are passing on this PR. Happy to rebase onto current main if that helps, since the salvage attempt in #10195 got closed. Let me know if there's anything else needed to move this forward.

@Bartok9

Bartok9 commented Jul 22, 2026

Copy link
Copy Markdown

Nice — thanks for signing the CLA, @SarthakB11. My salvage #10195 is already closed in favor of this one, so this is good to go on its own. Full credit to you 🙏

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.

mo.lazy does not show latest output

2 participants