Common issues and solutions when working with Dash.
Cause: Exception raised inside callback function.
Solution:
- Check the terminal for the full traceback
- Enable debug mode:
app.run(debug=True) - Add error handling:
@app.callback(Output('out', 'children'), Input('in', 'value'), on_error=lambda e: f"Error: {e}")
def update(value):
...Cause: Callback references component ID that doesn't exist in layout.
Solutions:
- Check for typos in component IDs
- For dynamic layouts, set
suppress_callback_exceptions=True:
app = Dash(__name__, suppress_callback_exceptions=True)- Use pattern-matching callbacks for dynamic components
Cause: Callback output is also its own input (directly or indirectly).
Solution: Restructure callbacks to break the cycle. Use State instead of Input where possible, or split into multiple callbacks.
Possible causes:
prevent_initial_call=Trueblocking first execution- Input component doesn't exist yet (dynamic layout)
- Component ID mismatch (check spelling, check dict IDs match exactly)
Debug: Add print() at callback start to verify it's being called.
Cause: Passing non-component to layout (e.g., raw dict, unsupported type).
Solution: Ensure all layout children are Dash components, strings, or numbers:
# Wrong
html.Div([{'key': 'value'}])
# Right
html.Div([html.Span('value')])Possible causes:
- Missing
idprop (required for callbacks) - JavaScript error - check browser console
- Component library not installed or imported
Debug: Check browser DevTools console for errors.
Cause: Using old import style.
Solution: Use new unified imports:
# Old (deprecated)
import dash_core_components as dcc
import dash_html_components as html
# New
from dash import dcc, htmlCause: Feature not available in installed Dash version.
Solution: Upgrade Dash:
pip install --upgrade dashCause: Port 8050 (or specified port) is occupied.
Solutions:
- Use different port:
app.run(port=8051) - Kill existing process:
lsof -i :8050thenkill <PID> - Set via environment:
PORT=8051 python app.py
Possible causes:
debug=False(hot reload requires debug mode)- File outside watched directories
- Syntax error preventing reload
Solution:
app.run(
debug=True,
dev_tools_hot_reload=True,
extra_hot_reload_paths=['./custom_modules/']
)Cause: Accessing Flask context outside request (e.g., in background thread).
Solution: Use flask.current_app inside callbacks, or pass data explicitly rather than using context.
Possible causes:
- Manager not configured correctly
- Celery worker not running (for CeleryManager)
- Exception in callback (check worker logs)
Debug: Check diskcache directory or Celery worker output for errors.
Cause: Process terminated unexpectedly.
Solution: Check for exceptions in the callback. Ensure psutil is installed.
Cause: set_progress not being called, or wrong output specified.
Solution: Ensure progress parameter matches an Output that exists:
@app.callback(
Output('result', 'children'),
Input('btn', 'n_clicks'),
progress=Output('progress', 'children'), # Must exist in layout
background=True,
manager=manager,
)
def compute(set_progress, n):
set_progress("Working...") # Call this
...Cause: Using async def callback without async dependencies.
Solution:
pip install dash[async]Cause: Conflicting event loops.
Solution: Dash automatically applies nest_asyncio in Jupyter. If issues persist:
import nest_asyncio
nest_asyncio.apply()Possible causes:
- Files don't contain
register_page(__name__) - Files start with
_or.(ignored) - Wrong
pages_folderpath
Solution: Ensure each page file has:
from dash import register_page
register_page(__name__)
layout = ...Cause: Path mismatch or routing issue.
Debug: Check dash.page_registry to see registered pages and their paths:
from dash import page_registry
print(list(page_registry.values()))Cause: Options list reference didn't change (same list object).
Solution: Return new list object:
# Wrong - mutating existing list
options.append(new_option)
return options
# Right - return new list
return options + [new_option]Possible causes:
- Returning same figure object (reference equality)
- Missing
figurein Output
Solution: Create new figure object:
return go.Figure(data=[...], layout={...}) # New object each timeSolutions:
- Enable virtualization:
virtualization=True - Use pagination:
page_size=20, page_action='native' - Filter data server-side before sending
Error: "session not created: This version of ChromeDriver only supports Chrome version X"
Solution: Update ChromeDriver to match your Chrome version:
# Check Chrome version
google-chrome --version
# Install matching chromedriver
pip install chromedriver-autoinstallerPossible causes:
- Callback never completing
- Element selector not finding element
- Timeout too short
Solution: Add explicit waits with longer timeout:
dash_duo.wait_for_text_to_equal("#output", "expected", timeout=30)Cause: Element hidden, overlapped, or not yet rendered.
Solution: Wait for element to be visible:
dash_duo.wait_for_element("#button")
element = dash_duo.find_element("#button")
element.click()Possible causes:
- Node modules not installed:
npm ci - Syntax error in React component
- Missing dependencies
Solution: Check build output, ensure npm ci was run in component directory.
Cause: Python package not installed in editable mode.
Solution:
pip install -e .Solutions:
- Use
eager_loading=False(default) for lazy component loading - Minimize assets in
assets/folder - Use
serve_locally=Falseto serve from CDN
Solutions:
- Use
background=Truefor expensive computations - Cache results with
@cache.memoizeor similar - Use clientside callbacks for simple transformations
- Reduce data sent to/from server
Possible causes:
- Storing data in global variables
- Background callback results not being cleaned up
- Large figures being cached
Solution: Use dcc.Store for state, set expire on background managers, avoid global mutable state.