Act Fast When Streamlit Apps Return Errors

If you’ve deployed a Streamlit app, you’ve probably seen it: the red screen when something goes wrong. In development, it’s annoying. In production, it’s invisible unless a user tells you!
This post shows you how to catch unhandled exceptions so you can run arbitrary tasks such as logging, alerts or AI workflows. It is geared toward developers self-deploying open source Streamlit as well as those deploying Streamlit in Snowflake.
When your app returns errors, you should know — and be able to do something about it.

In the data team at Snowflake, we set up a Slack notification within that handler, so we’re immediately aware of any app issues.

Core implementation
Fortunately, there’s a way to run custom logic whenever an exception arises in your app, enabling you to capture additional context and send it to any logging or notification system. We’ll show you how to:
Create a custom exception handler. This is where we define what we’d like to run anytime the app crashes.
Override Streamlit’s global exception handler with the custom one.
Enjoy!
Step 1: Create a custom exception handler
The exception handler is a Python function that takes the exception object as an argument. For example, below is a custom exception handler that behaves like the default one (showing the exception with st.exception
) but also logs it and sends notifications.
import traceback
from datetime import datetime
import streamlit as st
def custom_exception_handler(exception: Exception) -> None:
"""
Custom exception handler that logs exception data and sends notifications.
You can customize the logging destination and notification methods.
"""
# Still show the exception to the user (default behavior)
st.exception(exception)
# Collect context about the exception
exception_data = {
"exception_name": str(exception),
"traceback": str(traceback.format_exc()).strip(),
"user_name": getattr(st.user, 'user_name', 'unknown') if hasattr(st, 'user') else "unknown",
"timestamp": datetime.now().isoformat(),
"app_name": "your_app_name", # Replace with actual app identification
"page_name": "current_page", # Replace with actual page identification
}
# Log the exception (choose your method)
log_exception(exception_data)
# Send notifications if needed
send_notifications(exception_data)
You can log exceptions to various destinations. Below, we show examples for apps that can connect to Snowflake.
Option 1: Database table
A natural candidate is a custom, dedicated table in Snowflake, in which you can then append records.
def log_exception_to_table(exception_data: dict) -> None:
"""Log exception to a database table for later analysis"""
session = get_session()
# Insert into exceptions table
insert_sql = """
INSERT INTO app_exceptions (
exception_name, traceback, user_name, timestamp,
app_name, page_name
) VALUES (?, ?, ?, ?, ?, ?)
"""
session.sql(insert_sql, [
exception_data["exception_name"],
exception_data["traceback"],
exception_data["user_name"],
exception_data["timestamp"],
exception_data["app_name"],
exception_data["page_name"]
]).collect()
Option 2: Snowflake telemetry
Instead of creating a custom table, you may use the native Snowflake telemetry framework. First, make sure you’ve enabled telemetry collection. Then import snowflake.telemetry
, and logging is as easy as writing one line of code.
from snowflake import telemetry
def log_exception_to_telemetry(exception_data: dict) -> None:
"""Log exception using Snowflake's telemetry system"""
telemetry.add_event(
name="Uncaught exception in streamlit app",
attributes=exception_data
)
If you want to do anything more with that data, though, you probably want to create a downstream table that filters down only to relevant events, because events tables are huge.
Step 2: Override the global exception handler
Now you want the app to use the custom exception handler and not the default. Luckily, there’s an extra for that.
First, install streamlit-extras and make sure it’s in your app dependencies.
pip install streamlit-extras
Then call the following code in your main app module streamlit_app.py
.
import streamlit as st
from streamlit_extras.exception_handler import set_global_exception_handler
set_global_exception_handler(custom_exception_handler)
# Rest of the app!
That’s it! This function replaces Streamlit’s built-in exception handler with your custom one.
Step 3: Enjoy! And do something with that data
Once the exceptions data is stored, you can set up automations to be notified using, for instance, Snowflake alerts and notifications (email, Slack, webhooks). Our team uses Slack alerts, which have proven very useful. More ideas:
Ask a Snowflake Cortex Agent for help directly from Slack.
If you’re developing locally, why not ask Snowflake Cortex AI to suggest a fix?
Track how frequently your app goes down and set up a service-level agreement with your stakeholders.
Be creative, and please let me know what you build!