Data Science

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.

Flowchart image of reactions to app not working properly
Figure 1: When your Streamlit app isn't working properly (left), learn how to quickly react.

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

Example of Slack alert
Figure 2: An example of a Slack alert after a prod app stopped working.

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:

  1. Create a custom exception handler. This is where we define what we’d like to run anytime the app crashes.

  2. 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! 

Share Article

Subscribe to our blog newsletter

Get the best, coolest and latest delivered to your inbox each week

Where Data Does More

  • 30-day free trial
  • No credit card required
  • Cancel anytime