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 and df = ... 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 as pip 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 cell H9.

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 to bf.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.OUTPUT or =BF.FUNCTION.
  • Resolution: Excel serial numbers carry no time zone. Convert first: value.astimezone(zone).replace(tzinfo=None). Datetime values read from bf.ref are already naive.

9. ExcelResultConversionError: Python set results are intentionally unsupported...

  • Cause: Returning a Python set as 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 H2 for 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 None for a cell.
  • Resolution: In Excel, Python None formats as the text "None" (via a custom number format 0;-0;"None"). In website demos, it coerces to 0. If you want a visually empty cell, pad the spill with the empty string "" instead of None.

14. Uploaded notebook fails to start or parse

  • Cause: An uploaded .py script 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 H2 for a StartupError.

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.errors for 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={...} or functions={...} mapping of the currently displayed bf.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 def for 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

  1. Do not use plt.show(): In Marimo, Matplotlib figures are displayed by making the Figure or Axes object the cell’s final expression. Using plt.show() does nothing in the browser runtime.
  2. Do not access inputs with attribute syntax: Always use inputs["name"], not inputs.name. Attribute access conflicts with internal Anywidget methods and properties.
  3. Do not declare multiple bf.inputs widgets: Exactly one bf.inputs(...) call is permitted per notebook. Consolidate all workbook range references and table selections into that single call.
  4. 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.
  5. 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.
  6. 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!.