Troubleshooting and FAQ
Common errors, root causes, and FAQ.
This section catalogs common errors encountered when developing and running Boardflare notebooks, their root causes, and standard resolutions.
Common Errors & Resolutions
1. MultipleDefinitionError
- Cause: Two or more Marimo cells define the same variable name at the module scope (e.g.
df = ...in Cell 1 anddf = ...in Cell 2). - Resolution: Variable names must be globally unique across all cells. Prefix intermediate variables with an underscore (e.g.
_df), encapsulate them within local functions, or merge related logic into a single cell.
2. ModuleNotFoundError: No module named '...'
- Cause: Attempting to import a package that is not available in the Pyodide WebAssembly runtime or pre-bundled companion list.
- Resolution: When this happens in a notebook cell, the error in the response JSON (
H2) includes a pointer to the package list. Dynamic installation (such aspip install) is not supported. Check the pre-bundled package list and import only packages on it; do not add a PEP 723 header. If a package is not on the list, implement the logic using standard libraries or supported alternatives (e.g.scipy,numpy,pandas).
3. LayoutError: Row A... looks like the notebook header
- Cause: Header code (
import marimo,# /// script,app = marimo.App(...)) was placed in Column A of_BOARDFLARE. - Resolution: Column A holds only real Marimo cells (starting with
@app.cell,@app.function, etc.). All preamble and setup code belongs verbatim in cellH9.
4. Downstream cell waits for the workbook’s first input snapshot
- Cause: A downstream cell attempted to read
inputs["name"]before the initial workbook data arrived. - Resolution: Ensure the cell containing
inputs = bf.inputs(...)is displayed. In reactive cells, reading a required input before the first snapshot stops the current cell and its descendants, so no placeholder value is ever published, and Marimo reruns them once the snapshot arrives.
5. RuntimeError: Only one bf.inputs(...) is allowed per notebook; use one bf.inputs(...) with all inputs
- Cause: A notebook declared more than one
bf.inputs(...)widget across cells. - Resolution: Consolidate all workbook inputs (ranges, named references, and table selections) into a single
bf.inputs(...)call in one cell.
6. Table input includes header row as data
- Cause: A bare table name (e.g.
orders="Orders") was passed tobf.inputs(). In Excel, bare table names include the header row. - Resolution: Use
bf.ref("Orders", headers=True)so column names are taken from the first row and excluded from the data rows.
7. TypeError: Boardflare function ... cannot require keyword-only arguments
- Cause: A Python function published via
bf.publish(functions={...})declared a required keyword-only argument or**kwargs. - Resolution: Published worksheet functions take positional parameters with optional trailing defaults, optional
*args, and keyword-only parameters that have defaults. Replace required keyword-only parameters with positional parameters and remove**kwargs.
8. ExcelResultConversionError: Boardflare published value is a timezone-aware datetime; Excel stores wall-clock values, ...
- Cause: Publishing a timezone-aware datetime or time to Excel via
=BF.OUTPUTor=BF.FUNCTION. - Resolution: Excel serial numbers carry no time zone. Convert first:
value.astimezone(zone).replace(tzinfo=None). Datetime values read frombf.refare already naive.
9. ExcelResultConversionError: Python set results are intentionally unsupported...
- Cause: Returning a Python
setas an output or function result. - Resolution: Python set iteration is non-deterministic. Convert the set to a sorted list before publishing:
sorted(my_set).
10. Formula displays #NAME? in Excel
- Cause: Excel does not recognize
=BF.OUTPUT(...)or=BF.FUNCTION(...). - Resolution: Confirm the Boardflare add-in is installed and enabled for the workbook. If the add-in is running, check for typos in the formula name.
11. Formula displays #BUSY! indefinitely
- Cause: The shared runtime encountered a startup timeout or a synchronous Python function blocked the event loop.
- Resolution: Check the response JSON in
H2for startup errors. Ensure published functions are lightweight and do not contain blocking operations or infinite loops.
12. Formula displays #SPILL! in Excel
- Cause: The published output (matrix, Series, or DataFrame) cannot expand because existing cells, formulas, or formatting block the spill range.
- Resolution: Clear all non-empty cells below and to the right of the anchor cell containing
=BF.OUTPUT(...).
13. None displays as "None" in Excel or 0 in Web Demos
- Cause: The notebook returned
Nonefor a cell. - Resolution: In Excel, Python
Noneformats as the text"None"(via a custom number format0;-0;"None"). In website demos, it coerces to0. If you want a visually empty cell, pad the spill with the empty string""instead ofNone.
14. Uploaded notebook fails to start or parse
- Cause: An uploaded
.pyscript breaks the upload rules, contains syntax errors, uses unsupported packages, or fails during startup execution. - Resolution: Use Restore saved notebook in the recovery strip to discard the upload (see Reset and Recovery).
15. “Notebook initialization timed out”
- Cause: The notebook frontend did not report ready within the Notebook Startup Timeout in System Limits.
- Resolution: Click Retry. Use Reset saved notebook only when the saved source should be discarded. See Reset and Recovery.
16. “Notebook failed to start”
- Cause: The notebook runtime or the saved source could not be loaded.
- Resolution: The recovery strip offers Retry and Reset saved notebook. Check the response JSON in
H2for aStartupError.
18. Inputs do not update
- Cause: The
bf.inputs(...)widget is not displayed, a reference does not resolve, or the host lacks automatic workbook-change notifications (Google Sheets needs the manual Refresh button). - Resolution: Display the widget, correct the references, and inspect
inputs.errorsfor invalid, oversized, or unavailable references.
19. Formula reports that the notebook is not running (#N/A in Excel)
- Cause: The notebook session stopped or failed. Outputs and functions exist only while the session runs.
- Resolution: Retry or restart the session. In Excel the task pane does not have to be visible for formulas to start the notebook; open the Notebook tab to inspect or recover it.
20. Unknown notebook output or function (#VALUE! in Excel)
- Cause: The name is not in the
outputs={...}orfunctions={...}mapping of the currently displayedbf.publish()cell, differs in case, or the publication has not been published yet. - Resolution: Match the exact, case-sensitive name and check
publication.consumers.
21. A function stays busy
- Cause: A synchronous function is long-running or blocked. Cancellation and timeout keep a stale result from reaching the worksheet but cannot interrupt Python code that is already running.
- Resolution: Make the function short, or use
async deffor long work.
22. Changes disappeared after a restart
- Cause: The edits were not saved before the editor restarted, or they were made in a website demo (see Website Demos).
- Resolution: Wait for Saved in the footer before closing the pane or restarting.
Anti-Patterns to Avoid
- Do not use
plt.show(): In Marimo, Matplotlib figures are displayed by making theFigureorAxesobject the cell’s final expression. Usingplt.show()does nothing in the browser runtime. - Do not access inputs with attribute syntax: Always use
inputs["name"], notinputs.name. Attribute access conflicts with internal Anywidget methods and properties. - Do not declare multiple
bf.inputswidgets: Exactly onebf.inputs(...)call is permitted per notebook. Consolidate all workbook range references and table selections into that single call. - Do not execute blocking operations inside
=BF.FUNCTION: Worksheet functions share a single Python thread in the browser. Avoid long synchronous loops, heavy recalculations, or blocking delays in functions; move intensive modeling into reactive notebook cells and publish lightweight lookup functions or completed results. - Do not attempt network requests: The notebook runtime executes in a zero-network Pyodide WebAssembly sandbox. Calls to
urllib,requests, or raw sockets will fail. - Do not place static content in dynamic spill ranges: Keep dashboard layout areas separate from output spill paths so future row/column expansions never trigger
#SPILL!.