Streamlit error message: st.error vs st.exception vs st.stop (tested)

st.error("msg") shows a red box but does not stop your app; st.exception(ex) shows a caught exception with its traceback; to halt on bad input use st.error(...) then st.stop(). To hide tracebacks of uncaught errors from users, set client.showErrorDetails.

1. st.error, st.exception, st.stop: what each one does

b1.py runs three small apps with streamlit.testing.v1.AppTest and prints what ends up on the page:

from streamlit.testing.v1 import AppTest
app = '''
import streamlit as st
st.error("Could not load data.csv", icon="🚨")
try:
    1 / 0
except ZeroDivisionError as ex:
    st.exception(ex)
st.warning("Using cached data")
st.write("still running")
'''
at = AppTest.from_string(app).run()
print("st.error  ->", [(e.value, e.icon) for e in at.error])
print("st.exception ->", [e.message for e in at.exception], "| is_warning:", at.exception[0].is_warning)
print("st.warning ->", [w.value for w in at.warning])
print("markdown after errors ->", [m.value for m in at.markdown])

crash = '''
import streamlit as st
st.write("before")
1 / 0
st.write("after")
'''
at = AppTest.from_string(crash).run()
print("uncaught ->", [e.message for e in at.exception], "| markdown:", [m.value for m in at.markdown])

stop = '''
import streamlit as st
name = st.text_input("Name")
if not name:
    st.error("Please enter a name")
    st.stop()
st.write(f"Hello {name}")
'''
at = AppTest.from_string(stop).run()
print("st.stop  ->", [e.value for e in at.error], "| markdown:", [m.value for m in at.markdown], "| exceptions:", len(at.exception))
at.text_input[0].input("Ada").run()
print("after input ->", [e.value for e in at.error], "| markdown:", [m.value for m in at.markdown])

Output (streamlit 1.66.1, Python 3.13.5):

st.error  -> [('Could not load data.csv', '🚨')]
st.exception -> ['division by zero'] | is_warning: False
st.warning -> ['Using cached data']
markdown after errors -> ['still running']
uncaught -> ['division by zero'] | markdown: ['before']
st.stop  -> ['Please enter a name'] | markdown: [] | exceptions: 0
after input -> [] | markdown: ['Hello Ada']

2. Hide tracebacks from users: client.showErrorDetails

For uncaught exceptions, the client.showErrorDetails option (default full) controls what the browser shows. From the option's own description in streamlit 1.66.1: "full" shows exception types, messages and tracebacks; "stacktrace" shows types, generic messages and tracebacks; "type" shows only types and generic messages, with details printed to the console. Set it in .streamlit/config.toml:

[client]
showErrorDetails = "type"

Or on the command line: streamlit run app.py --client.showErrorDetails=type. For errors you expect, catch them and use st.error with a message written for the user instead.

Related: StreamlitAPIException: duplicate key and session_state.

Frequently asked questions

Does st.error stop a Streamlit app?

No. It only displays a message; call st.stop() after it to halt the run.

How do I show a traceback in Streamlit?

Catch the exception and pass it to st.exception(ex); the script continues afterwards.

How do I hide error details from Streamlit users?

Set showErrorDetails = "type" under [client] in .streamlit/config.toml, or pass --client.showErrorDetails=type.

Written with AI assistance. Measured on 2026-10-23 with streamlit 1.66.1 and Python 3.13.5 on Linux, using streamlit.testing.v1.AppTest. Scripts ran verbatim and the output was pasted unedited. PlainTables is our extension; Streamlit is free.