nautechsystems/nautilus_trader · error · ValueError
Chart renderer must be callable, was {type(renderer)}
Error message
Chart renderer must be callable, was {type(renderer)} What it means
register_tearsheet_chart validates that the renderer argument is callable; anything else (a called result, a None default, an object) is rejected with the offending type in the message. The renderer is later invoked as renderer(fig=..., row=..., col=..., **kwargs) during figure assembly, so a non-callable would fail much later and less clearly.
Source
Thrown at python/nautilus_trader/analysis/tearsheet.py:2468
Display title for the subplot.
renderer : Callable
Function that adds traces to the figure. Signature:
renderer(fig, row, col, returns, stats_pnls, stats_returns, stats_general,
theme_config, benchmark_returns, benchmark_name, run_info, account_info, engine, **kwargs)
Raises
------
ValueError
If name is empty or renderer is not callable.
"""
_require_not_none(name, "name")
if not name.strip():
raise ValueError("Chart name cannot be empty")
if not callable(renderer):
raise ValueError(f"Chart renderer must be callable, was {type(renderer)}")
_TEARSHEET_CHART_SPECS[name] = {
"type": subplot_type,
"title": title,
"renderer": renderer,
}
def _calculate_grid_layout(
charts: list[TearsheetChart],
custom_layout: Any = None,
) -> tuple[int, int, list, list[str], list[float], float, float]:
"""
Calculate dynamic grid layout based on selected charts.
Parameters
----------
charts : list[TearsheetChart]View on GitHub (pinned to a4b06ed870)
Solutions
- Pass the function object itself: register_tearsheet_chart('x', 'xy', 'T', render_chart) with no parentheses
- If wrapping an instance, give the class a __call__ method or pass a lambda closing over it
- Confirm with callable(renderer) before registering
Example fix
# before register_tearsheet_chart(name='c', subplot_type='xy', title='T', renderer=render_chart()) # ValueError: Chart renderer must be callable, was Figure # after register_tearsheet_chart(name='c', subplot_type='xy', title='T', renderer=render_chart)
Defensive patterns
Strategy: type-guard
Validate before calling
if not callable(renderer):
raise TypeError(f'renderer must be callable, got {type(renderer).__name__}')
register_tearsheet_chart(name, 'xy', title, renderer) Type guard
from typing import Callable
def is_renderer(obj: object) -> bool:
return callable(obj) Try / catch
try:
register_tearsheet_chart(name, 'xy', title, renderer)
except ValueError as e:
raise TypeError('Pass the function itself, not its result') from e Prevention
- Register functions by reference (no parentheses) or via the decorator form
- Lint for common 'fn()' where 'fn' is expected in registration helpers
When it happens
Trigger: Passing renderer=render_chart() (calling the function, yielding its return value) instead of renderer=render_chart; passing a class instance without __call__; passing None or a string.
Common situations: Decorators/call-results mistaken for functions; wrapper objects that forgot __call__; copy-paste from an example where parentheses were added.
Related errors
- No tearsheet chart registered under '{chart_name}'.{hint} Re
- Grid has {rows * cols} cells but {len(charts)} charts were c
- value must be datetime-like
- {name} must not be None
- Theme '{name}' not found.{suggestion_text} Available themes:
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/37a231d6178f7985.
Report an issue: GitHub.