Streamlit App freezes after submitting form

Summary

Hi everybody!
I am using Streamlit to combine plotly visualisations with a survey using st.form.
Some users that accessed the app on their phones reported that the app froze after they hit the submit button. Unfortunately, I am unable to reproduce their error. I only have a vague idea that my handling of session state might be part of the problem. I describe my suspicion in more detail below.

Steps to reproduce

The app has three pages. The first, main page only holds an image. The second page loads and displays data and holds a st.form. Submitted st.form’s are sent to a private google sheet using the shillelagh package. This is the page where the error occurred. The third page loads the data from the same google sheet, and filters and displays todays submissions.

Here’s why I assume that session state might be the reason for the bug:
The order in which the graphs(“scenarios”) are displayed on page 2 is randomised. To randomise within a st.form and not lose widget values after submitting, I thought it’s clever to set random.seed(st.session_state.rs) with rs being a random state initialized earlier. However, when I display st.session_state.rs in multiple tabs of the app, I realised that the app only generates three random numbers as rs, namely 37, 81 and 95. This is independent from device or browser.
I tried submitting forms with the same session_state from multiple devices and multiple browsers at the same time, and it always worked for me. Do you have any ideas how I could reproduce the error, ie. the freezing of the app? Is it related to the fact that multiple users having the same session_state at the same time?

Code snippets
I used this code in the second page to initialize the session state and randomise the order of graphs/ scenarios:

#set random session state
if 'rs' not in st.session_state:
    st.session_state['rs'] = random.randint(1, 100)

st.write(st.session_state.rs)

#randomly order scenarios/ graphs, based on random.seed that takes session_state.rs as input
def random_scenario_order():
    random.seed(st.session_state.rs)
    scenario_list = ["Scenario \u25B2", "Scenario \u25A0", "Scenario \u25C6"]
    scenario_list_nutr = random.sample(scenario_list, len(scenario_list))
    scenario_list_tran = random.sample(scenario_list, len(scenario_list))
    scenario_list_buil = random.sample(scenario_list, len(scenario_list))
    scenario_list_gdp = random.sample(scenario_list, len(scenario_list))
    return scenario_list_nutr, scenario_list_tran, scenario_list_buil, scenario_list_gdp

scenario_list_nutr, scenario_list_tran, scenario_list_buil, scenario_list_gdp = random_scenario_order()

and this code to load the form to the google sheets:

#prepare google sheet connection
sheet_url = st.secrets["private_gsheets_url"]

#@st.cache_data
def create_connection():
        credentials = service_account.Credentials.from_service_account_info(
        st.secrets["gcp_service_account"], 
        scopes=["https://www.googleapis.com/auth/spreadsheets",],)
        connection = connect(":memory:", adapter_kwargs={
            "gsheetsapi" : { 
            "service_account_info" : {
                "type" : st.secrets["gcp_service_account"]["type"],
                "project_id" : st.secrets["gcp_service_account"]["project_id"],
                "private_key_id" : st.secrets["gcp_service_account"]["private_key_id"],
                "private_key" : st.secrets["gcp_service_account"]["private_key"],
                "client_email" : st.secrets["gcp_service_account"]["client_email"],
                "client_id" : st.secrets["gcp_service_account"]["client_id"],
                "auth_uri" : st.secrets["gcp_service_account"]["auth_uri"],
                "token_uri" : st.secrets["gcp_service_account"]["token_uri"],
                "auth_provider_x509_cert_url" : st.secrets["gcp_service_account"]["auth_provider_x509_cert_url"],
                "client_x509_cert_url" : st.secrets["gcp_service_account"]["client_x509_cert_url"],
                }
            },
        })
        return connection.cursor()
##
##
# I am skipping the lines of the st.form. It's basically 22 widgets (q1 - q22) 
##
##

#submitting form
submitted = st.form_submit_button("Click here to submit!")
        if submitted:
            cursor = create_connection()
            query = f'INSERT INTO "{sheet_url}" VALUES ("{q1}", "{q2}", "{q3}", "{q4}", "{q5}", "{q6}", "{q7}", "{q8}", "{q9}", "{q10}","{q11}","{q12}","{q13}","{q14}","{q15}","{q16}","{q17}","{q18}","{q19}","{q20}","{q21}","{q22}", "{timestamp}")'
            cursor.execute(query)
            st.write("**:green[Submission successful. Thank you for your input!]**")

If applicable, please provide the steps we should take to reproduce the error or specified behavior.

Expected behavior:

I would have expected that each tab has it’s own unique session_state.

Actual behavior:

Random session state is repeating itself after three tabs.
However, I want to mention again that the app and the form submission works perfectly fine within my tests. The bug I want to fix and which I cannot reproduce is that the app seems to freeze when some users hit the submit button on their phones.

Debug info

conda version : 23.3.1
conda-build version : 3.24.0
python version : 3.10.11.final.0
streamlit: 1.23.1

Requirements file

pyam-iamc==1.8.0
pillow==9.5.0
plotly==5.14.1
streamlit_survey==0.1.0
shillelagh
google-auth>=1.23.0,<2
gspread
google
pydrive
gspread_dataframe
gsheetsdb

Links

Hi @zyankarli

Thanks for your question and for providing a detailed walkthrough of the situation. I can see that you’ve done a great job deducing the root cause and it’s rather difficult to actually find the exact cause as there is a multitude of possibilities. Have you tried asking the user which internet browser, which version, and on which phone device gave the error? Perhaps with this precise information, one can test and evaluate further.

Best regards,
Chanin

Hi @dataprofessor!

Thank you so much for your kind reply. Unfortunately, I was not in the room when the error occurred and no technical data was collected on the respective devices. I understand that without any additional information, it will be almost impossible to identify the error source.

Do you, or anyone else, have suggestions for new streamlit users like me on how one could test an app before deployment on different internet browser and version as well as phone devices on whether the submit button works? Is there software out there that would allow me to automate such a testing process?

The only software I found focuses on testing the visual representation, but did not touch upon testing submitting a form.
Cheers!

1 Like

Hi @zyankarli

BrowserStack seems to be what you’re looking for although I have not used it before.

Hope this helps!

Best regards,
Chanin

Turns out that some iPhone security settings don’t allow to submit streamlit forms!
My encountered problem can be overcome by changing the security settings on the phone.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.