debugging-streamlit
Original:🇺🇸 English
Translated
Debug Streamlit frontend and backend changes using make debug with hot-reload. Use when testing code changes, investigating bugs, checking UI behavior, or needing screenshots of the running app.
4installs
Sourcestreamlit/streamlit
Added on
NPX Install
npx skill4agent add streamlit/streamlit debugging-streamlitTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Debugging Streamlit Apps
Quick Start
bash
make debug my_app.pyThis starts both backend (Streamlit/Python) and frontend (Vite/React) with hot-reload. The app URL is printed on startup (default ; is reserved for manual ; it may use if other debug sessions are running). Avoid pinning unless you have a specific hard requirement (last resort).
http://localhost:30013000make frontend-dev3002+VITE_PORTHot-reload behavior:
- Frontend: Changes to code are applied within seconds.
frontend/ - Backend: Only changes to the app script trigger a rerun. Changes to the Streamlit library itself () require restarting
lib/streamlit/.make debug
Log Files
Each run writes logs to a per-session directory under and updates to point at the most recent session.
Because is a symlink, it can move if multiple debug sessions are starting/stopping concurrently—prefer using the session directory path printed by when you need stable log references.
You can find the exact session directory in the startup output under the section.
make debugwork-tmp/debug/work-tmp/debug/latest/latest/*make debugmake debugLog files| File | Content |
|---|---|
| Python |
| Browser |
Logs are cleared at the start of each session and persist after exit for post-mortem analysis.
Log size warning: Logs can grow large during extended debugging sessions. Instead of reading entire log files, use to search for specific patterns:
rgbash
# Search for specific debug messages
rg "DEBUG:" work-tmp/debug/latest/backend.log
# Search for errors (case-insensitive)
rg -i "error|exception|traceback" work-tmp/debug/latest/backend.log
# Search with context (3 lines before/after)
rg -C 3 "my_function" work-tmp/debug/latest/backend.log
# Search frontend logs for specific component
rg "MyComponent" work-tmp/debug/latest/frontend.logUse this directory for all debugging artifacts (scripts, screenshots, etc.) to keep them organized.
Adding Debug Output
Backend (Python):
python
print(f"DEBUG: session_state = {st.session_state}")Frontend (TypeScript/React):
typescript
console.log("DEBUG: props =", props)Frontend output appears in (or the current session's file).
console.log()work-tmp/debug/latest/frontend.logfrontend.logWorkflow
- Create or use a test script in (e.g.,
work-tmp/debug/)work-tmp/debug/test_feature.py - Run
make debug work-tmp/debug/test_feature.py - Verify startup: Check for
work-tmp/debug/latest/backend.log/ErrorandExceptionfor console errors to ensure both servers started correctlywork-tmp/debug/latest/frontend.log - Access the printed App URL in your browser (default , but it may be
http://localhost:3001)3002+ - Verify script execution: Check again for any errors after the first app access
work-tmp/debug/latest/backend.log - Monitor logs by inspecting and
work-tmp/debug/latest/backend.logwork-tmp/debug/latest/frontend.log - Edit code - changes apply automatically via hot-reload
- Check logs for debug output
Quick error check:
bash
# Backend errors
rg -i "error|exception" work-tmp/debug/latest/backend.log
# Frontend console errors
rg -i "error" work-tmp/debug/latest/frontend.logTemporary Playwright Scripts for Screenshots & Testing
For advanced debugging with screenshots or automated UI interaction.
Quick: Playwright CLI
For simple screenshots and interactions, use (available in frontend devDependencies):
@playwright/clibash
cd frontend
STREAMLIT_APP_URL=http://localhost:3001
yarn playwright-cli open "$STREAMLIT_APP_URL"
yarn playwright-cli screenshot --filename ../work-tmp/debug/screenshot.png --full-page
yarn playwright-cli closeCustom Scripts
For complex interactions, create temporary Playwright scripts in :
work-tmp/debug/python
# work-tmp/debug/debug_screenshot.py
"""Temporary Playwright script for debugging - run against make debug."""
import os
from playwright.sync_api import sync_playwright, expect
from e2e_playwright.shared.app_utils import get_text_input, click_button
from e2e_playwright.conftest import wait_for_app_loaded, wait_for_app_run
def main():
app_url = os.environ.get("STREAMLIT_APP_URL", "http://localhost:3001")
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page(viewport={"width": 1280, "height": 720})
# Connect to app started with `make debug`
page.goto(app_url)
wait_for_app_loaded(page)
# Interact with the app
text_input = get_text_input(page, "Name")
text_input.fill("Test User")
click_button(page, "Submit")
wait_for_app_run(page)
# Verify and screenshot
expect(page.get_by_text("Hello, Test User")).to_be_visible()
page.screenshot(path="work-tmp/debug/debug_screenshot.png", full_page=True)
print("Screenshot saved to work-tmp/debug/debug_screenshot.png")
browser.close()
if __name__ == "__main__":
main()Running Temporary Scripts
Ensure is running first (start it in a background task if needed). If your session is using a non-default port, set accordingly, then run the Playwright script:
make debug <app.py>make debugSTREAMLIT_APP_URLbash
STREAMLIT_APP_URL=http://localhost:3001 \
PYTHONPATH=. uv run python work-tmp/debug/debug_screenshot.pyThis uses the uv-managed environment with all dependencies (playwright, etc.) and makes importable without path manipulation.
e2e_playwrightAvailable Utilities from e2e_playwright
Element Locators & Interactions ():
Provides helpers like , , , , etc.
e2e_playwright.shared.app_utilsget_text_input()get_button()click_button()get_checkbox()Synchronization ():
e2e_playwright.conftest- - wait for initial load
wait_for_app_loaded(page) - - wait for script execution after interaction
wait_for_app_run(page) - - poll until condition is true
wait_until(page, fn, timeout)
Playwright API Reference: https://playwright.dev/python/docs/api/class-playwright
Screenshot Best Practices
python
# Full page screenshot
page.screenshot(path="work-tmp/debug/full.png", full_page=True)
# Element screenshot
element = page.get_by_test_id("stDataFrame")
element.screenshot(path="work-tmp/debug/dataframe.png")Troubleshooting
Port already in use / multiple sessions:
- will automatically pick a free frontend port (typically in the
make debugrange) so multiple debug sessions can run simultaneously.3001-3100 - Frontend port is reserved for manual
3000sessions.make frontend-dev - If you have a hard requirement for a specific frontend port, you can pin it with (last resort).
VITE_PORT=3002 make debug <app.py>
Hot-reload not working:
- Backend: Only the app script is watched. Changes to require restarting
lib/streamlit/.make debug - Frontend: Check for Vite errors. TypeScript errors can break HMR.
work-tmp/debug/latest/frontend.log
Playwright script fails to connect:
- Verify is running and healthy
make debug - Check the printed App URL is accessible in the browser
- Ensure is called after
wait_for_app_loaded(page)page.goto()
Cleanup
After debugging is complete, remove temporary scripts and screenshots from .
work-tmp/debug/