Skip to content

running script with persistent cache raises BlockException if there is other code in the cell #6186

@Light2Dark

Description

@Light2Dark

Describe the bug

This only happens when running as a script. The solution is to move the cache block to it's own cell, but it would be nice to get that as the error message.

When running python wip/cache_stuff.py

Traceback (most recent call last):
  File "/Users/shahmir/Development/marimo/wip/cache_stuff.py", line 36, in <module>
    app.run()
    ~~~~~~~^^
  File "/Users/shahmir/Development/marimo/marimo/_ast/app.py", line 605, in run
    ).run()
      ~~~^^
  File "/Users/shahmir/Development/marimo/marimo/_runtime/app/script_runner.py", line 228, in run
    raise e.__cause__ from None  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/shahmir/Development/marimo/marimo/_runtime/executor.py", line 138, in execute_cell
    exec(cell.body, glbls)
    ~~~~^^^^^^^^^^^^^^^^^^
  File "/Users/shahmir/Development/marimo/wip/cache_stuff.py", line 28, in <module>
    with mo.persistent_cache("random"):
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/shahmir/Development/marimo/marimo/_save/save.py", line 517, in __exit__
    raise instance from CacheException("Failure during save.")
  File "/Users/shahmir/Development/marimo/wip/cache_stuff.py", line 29, in <module>
    print(compute(1, 2))
    ^
  File "/Users/shahmir/Development/marimo/marimo/_utils/with_skip.py", line 71, in _trace
    self.trace(with_frame)
    ~~~~~~~~~~^^^^^^^^^^^^
  File "/Users/shahmir/Development/marimo/marimo/_save/save.py", line 466, in trace
    ).visit(
      ~~~~~^
        ast.parse(graph.cells[cell_id].code).body  # type: ignore[arg-type]
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/opt/homebrew/Cellar/[email protected]/3.13.5/Frameworks/Python.framework/Versions/3.13/lib/python3.13/ast.py", line 422, in visit
    return visitor(node)
  File "/Users/shahmir/Development/marimo/marimo/_ast/transformers.py", line 341, in generic_visit
    pre_block, with_block = super().generic_visit(node)
                            ~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/Users/shahmir/Development/marimo/marimo/_ast/transformers.py", line 314, in generic_visit
    raise BlockException(
    ...<3 lines>...
    )
marimo._ast.transformers.BlockException: cache cannot be invoked within a <class 'ast.Expr'> block (try moving the block within the cache scope).

Will you submit a PR?

  • Yes

Environment

{
  "marimo": "0.15.0",
  "editable": true,
  "OS": "Darwin",
  "OS Version": "24.6.0",
  "Processor": "arm",
  "Python Version": "3.13.5",
  "Binaries": {
    "Browser": "139.0.7258.139",
    "Node": "v22.13.0"
  },
  "Dependencies": {
    "click": "8.2.1",
    "docutils": "0.22",
    "itsdangerous": "2.2.0",
    "jedi": "0.19.2",
    "markdown": "3.8.2",
    "narwhals": "2.1.2",
    "packaging": "25.0",
    "psutil": "7.0.0",
    "pygments": "2.19.2",
    "pymdown-extensions": "10.16.1",
    "pyyaml": "6.0.2",
    "starlette": "0.47.2",
    "tomlkit": "0.13.3",
    "typing-extensions": "4.14.1",
    "uvicorn": "0.35.0",
    "websockets": "14.2"
  },
  "Optional Dependencies": {
    "altair": "5.5.0",
    "anywidget": "0.9.18",
    "duckdb": "1.3.2",
    "ibis-framework": "10.8.0",
    "nbformat": "5.10.4",
    "openai": "1.101.0",
    "pandas": "2.3.2",
    "polars": "1.32.3",
    "pyarrow": "21.0.0",
    "loro": "1.5.4",
    "pytest": "8.3.5",
    "python-lsp-server": "1.13.0",
    "ruff": "0.9.10",
    "sqlglot": "27.8.0"
  },
  "Experimental Flags": {
    "chat_sidebar": true,
    "secrets": true,
    "mcp_docs": true,
    "table_charts": true,
    "spreadsheet_editor": true,
    "rdg_data_editor": true,
    "multi_column": true,
    "inline_ai_tooltip": false,
    "tracing": true,
    "experimental_data_table": true,
    "lsp": true,
    "performant_table_charts": true,
    "rtc_v2": false,
    "data_table_plugin": true,
    "sql_linter": true,
    "sql_engines": false,
    "glide_data_editor": true,
    "sql_engine": true
  }
}

Code to reproduce

import marimo

__generated_with = "0.14.17"
app = marimo.App(width="medium")


@app.cell
def _():
    import marimo as mo
    return mo

@app.function
def compute(x, y):
    return x + y


@app.cell
def _(mo):
    with mo.persistent_cache("random"):
        print(compute(1, 2))

    [1,2,3]
    return


if __name__ == "__main__":
    app.run()

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions