Fix broken "Cell Output Must Be at the Top Level" example in notebook patterns

The previous "FIXED" example still had mo.md() called as a side effect
inside if/else blocks (never rendered) while mixing it with a DataFrame
in the same cell. Replace with the correct pattern: split into separate
cells where each displays exactly one thing at the top level.
This commit is contained in:
2026-02-10 20:26:05 -06:00
parent 1abb74705c
commit 438b380d04

View File

@@ -83,7 +83,7 @@ def fetch_details(client, DATAINDEX, results):
Marimo only renders the **last expression at the top level** of a cell as rich output. An expression buried inside an `if`/`else`, `for`, `try`, or any other block is **not** displayed — it's silently discarded.
**BROKEN**`_df` inside the `if` branch is never rendered:
**BROKEN**`_df` inside the `if` branch is never rendered, and `mo.md()` inside `if`/`else` is also discarded:
```python
@app.cell
@@ -93,26 +93,35 @@ def show_results(results, mo):
mo.md(f"**Found {len(results)} results**")
_df # Inside an if block — marimo does NOT display this
else:
mo.md("**No results found**")
mo.md("**No results found**") # Also inside a block — NOT displayed
return
```
**FIXED**assign inside the branches, display at the top level:
**FIXED**split into separate cells. Each cell displays exactly **one thing** at the top level:
```python
# Cell 1: build the data, return it
@app.cell
def show_results(results, mo):
_output = None
if results:
_output = pl.DataFrame(results)
mo.md(f"**Found {len(results)} results**")
else:
mo.md("**No results found**")
_output # Top-level last expression — marimo renders this
return
def build_results(results, pl):
results_df = pl.DataFrame(results) if results else None
return (results_df,)
# Cell 2: heading — mo.md() is the top-level expression (use ternary for conditional text)
@app.cell
def show_results_heading(results_df, mo):
mo.md(f"**Found {len(results_df)} results**" if results_df is not None else "**No results found**")
# Cell 3: table — DataFrame is the top-level expression
@app.cell
def show_results_table(results_df):
results_df # Top-level expression — marimo renders this as interactive table
```
**Rule of thumb:** initialize a `_output = None` variable before any conditional, assign the displayable value inside the branches, then put `_output` as the last top-level expression. When it's `None` (e.g., the `else` path), marimo shows nothing — which is fine since the `mo.md()` already provides feedback.
**Rules:**
- Each cell should display **one thing** — either `mo.md()` OR a DataFrame, never both
- `mo.md()` must be a **top-level expression**, not inside `if`/`else`/`for`/`try` blocks
- Build conditional text using variables or ternary expressions, then call `mo.md(_text)` at the top level
- For DataFrames, use a standalone display cell: `def show_table(df): df`
### Async Cells