I am sometimes encountering this error when navigating around my app. The session shuts down immediately.
Steps to reproduce
I am finding it hard to generate a reproducible example, so I would appreciate some help diagnosing the message to pinpoint the cause; I might be able to provide one after I figure out which element is causing the problem.
Please also see post below for more context:
Additional information
The exact error is: Failed to process a Websocket message (Error: Failed to retrieve ForwardMsg (hash=61709d322061634f0bd0f8dd94ac2a36): Not Found)
Relevant debug log:
2023-02-23 13:20:01.879 Removing orphaned files...
2023-02-23 13:20:01.941 Running script RerunData(query_string='', widget_states=None, page_script_hash='0ec3ea679097fa0a6f00970abb8f54e6', page_name='')
2023-02-23 13:20:01.941 Disconnecting files for session with ID 38355126-60ef-4d64-a7b2-62dc1e11d299
2023-02-23 13:20:01.941 Sessions still active: dict_keys([])
2023-02-23 13:20:01.941 Files: 0; Sessions with files: 0
2023-02-23 13:20:01.951 Removing orphaned files...
2023-02-23 13:20:02.018 Sending cached message ref (hash=61709d322061634f0bd0f8dd94ac2a36)
2023-02-23 13:20:02.018 Caching message (hash=61709d322061634f0bd0f8dd94ac2a36)
2023-02-23 13:20:02.018 Script run finished successfully; removing expired entries from MessageCache (max_age=2)
2023-02-23 13:20:02.091 in-event <InotifyEvent: src_path=b'/home/.../pages', wd=1, mask=IN_IGNORED, cookie=0, name=>
2023-02-23 13:20:02.092 in-event <InotifyEvent: src_path=b'/home/.../util', wd=1, mask=IN_IGNORED, cookie=0, name=>
2023-02-23 13:20:02.092 Shutting down (id=314b9d4f-4cc6-4403-8199-dc1c697d213e)
2023-02-23 13:20:02.093 Disconnecting files for session with ID 314b9d4f-4cc6-4403-8199-dc1c697d213e
2023-02-23 13:20:02.093 Sessions still active: dict_keys([])
2023-02-23 13:20:02.093 Files: 0; Sessions with files: 0
2023-02-23 13:20:02.093 Removing orphaned files...
2023-02-23 13:20:02.093 Runtime state: RuntimeState.ONE_OR_MORE_SESSIONS_CONNECTED -> RuntimeState.NO_SESSIONS_CONNECTED
I found something curious: this error is being triggered by buttons which (1) write an object (custom class with lots of text) to st.session_state and (2) use callbacks or st.experimental_rerun to refresh the page.
In local environment or testing deployment, I have a single st.write(st.session_state) statement at the end of my script. Removing that statement stops the error from happening.
I would like to get to the bottom of this, so I would welcome any hints that might lead in the right direction.
In my case everything was worked perfectly but after i upgraded to 1.18 it becoming very annoying because once i enter the app and try to perform any action it crash most of the time. But mostly when i try to use multiselect widget.
My app is connected to an sql server database.
Do you happen to have sharable code snippets that run into this issue?
No need for the repro to be totally minimal as it seems like a problem that’s difficult to isolate, but any relatively simple code snippet that demonstrates the problem would help.
Thanks for your interest in this. At the moment, the code which does this is quite complex and I was not able to make a reproducible example from the ground up; I will try to minimize the existing code instead and get back to you.
In the meantime, do you have any hints what this might refer to? In my case this seems to be directly caused by a st.write(st.session_state) statement which is a bit bizarre but could be caused by the interaction of session state with navigational elements (buttons with experimental_rerun / callbacks attached to them).
This does not break as reliably as my app ‘in the wild’. My app breaks if I go back and forth just twice, this requires a few more times. Since the breaking is reacting to the number of clicks and the amount of text, I suppose this could be some memory problem?
Please let me know if you can reproduce the error or if you think the example is too convoluted; I can try and tweak it some more.
import streamlit as st
def _init():
if "step" not in st.session_state:
st.session_state["step"] = 1
st.session_state["message"] = ""
class MessageForm:
def __init__(self, step: int, message: str) -> None:
self.step = step
self.message = message
def _save_state(self) -> None:
st.session_state["step"] = self.step
st.session_state["message"] = self.message
def _go_back(self) -> None:
self.step -= 1
self._save_state()
def _proceed(self) -> None:
self.step += 1
self._save_state()
st.experimental_rerun()
def form(self):
st.subheader(f"Step {self.step}: Input a message")
st.markdown("""
Write a message.
""")
with st.form(key="entry_form", clear_on_submit=False):
self.message = st.text_area("Message", value=self.message)
if st.form_submit_button(label="Submit", type="primary"):
self._proceed()
def display(self):
st.subheader(f"Step {self.step}: Show your message")
st.info(f"**Your message**: {self.message}")
def draw(self):
st.header("A form for breaking Streamlit")
st.button("Go back", disabled=(self.step < 2), on_click=self._go_back)
if self.step < 2:
self.form()
else:
self.display()
def main():
_init()
form = MessageForm(
step=st.session_state["step"],
message=st.session_state["message"])
form.draw()
if __name__ == "__main__":
main()
st.write(st.session_state)
Edit: a more minimal example without intermediate session state variables, seems to break more reliably too:
import streamlit as st
def _init():
if "form" not in st.session_state:
st.session_state["form"] = MessageForm(1, "")
class MessageForm:
def __init__(self, step: int, message: str) -> None:
self.step = step
self.message = message
def _go_back(self) -> None:
self.step -= 1
def _proceed(self) -> None:
self.step += 1
st.experimental_rerun()
def form(self):
st.subheader(f"Step {self.step}: Input a message")
st.markdown("""
Write a message.
""")
with st.form(key="entry_form", clear_on_submit=False):
self.message = st.text_area("Message", value=self.message)
if st.form_submit_button(label="Submit", type="primary"):
self._proceed()
def display(self):
st.subheader(f"Step {self.step}: Show your message")
st.info(f"**Your message**: {self.message}")
def draw(self):
st.header("A form for breaking Streamlit")
st.button("Go back", disabled=(self.step < 2), on_click=self._go_back)
if self.step < 2:
self.form()
else:
self.display()
def main():
_init()
st.session_state['form'].draw()
if __name__ == "__main__":
main()
st.write(st.session_state)
We were just discussing about this and discovered the bug that is causing this issue. We’ll get a fix for it out soon (hoping in the next ~2 weeks). Thank you all for reporting this and sorry for the friction this is causing!
Thanks for the code snippets @ennui! These should come in handy when I’m testing that the fix I’m working on for this issue.
As @jcarroll said, some discussion in a team meeting earlier led us to realize what’s going on here. I’ll be working on a fix for this sometime this week. We’ll hope to get the fix out in the 1.20.0 release happening soon. For now, downgrading to 1.17.0 should avoid the issue if you can temporarily make do without some of the newest features.