st.dialog closes very quickly

I have a form where the user picks some events to cancel, they pick rows from a dataframe, click the cancel button and then an st.dialog appears asking to confirm.

but for some reason the dialog window closes almost instantly after being opened without throwing a single error, at least that i can find, and even weirder is that this code is 90% copy pasted from another page i made where you cancel a different type of event and it works fine

broken code snippets:

if not st.user.is_logged_in:
    st.stop()

if 'erro_db' not in st.session_state:
    st.session_state['erro_db'] = False

pc = is_pc()

@st.dialog("Confirma o cancelamento?")
def confirmation_window():
    confirmacao = st.columns(2)
    with confirmacao[0]:
        if st.button("Sim", type="primary"):
            cancelar()             #cancel doesnt run since i dont even have time to click the button
            st.rerun()
    with confirmacao[1]:
        if st.button("Não", type="primary"):
            st.rerun()

selecionados = calen.selection.rows
if st.button("Cancelar reservas", type="primary"):
    if selecionados == []:
        st.error("Nenhuma reserva selecionada")
    else:
        reservas_formadores = ler_reservas_formadores(True)
        formadores = ler_formadores(True)            #reset cache, no streamlit command is used
        confirmation_window()


code from another file that works:

if not st.user.is_logged_in:
    st.stop()

if 'erro_db' not in st.session_state:
    st.session_state['erro_db'] = False

pc = is_pc()

@st.dialog("Confirma o cancelamento?")
def confirmation_window():
    confirmacao = st.columns(2)
    with confirmacao[0]:
        if st.button("Sim", type="primary"):
            cancelar()
            st.rerun()
    with confirmacao[1]:
        if st.button("Não", type="primary"):
            st.rerun()

selecionados = calen.selection.rows
if st.session_state['erro_db']:
    st.error("Erro na modificação. Alterações podem não ter sido realizadas.")
if st.button("Cancelar reservas", type="primary"):
    if selecionados == []:
        st.error("Nenhuma 
reserva selecionada")
    else:
        reservas_salas = ler_reservas_salas(True)
        salas = ler_salas(True)
        confirmation_window()

Hey there, thanks for sharing your code and welcome to the community! :partying_face: This is a classic Streamlit gotcha with dialogs: if you call st.dialog unconditionally (e.g., every rerun after the button is pressed), the dialog will open and then immediately close on the next rerun unless you control its invocation with session state. This happens because after you click “Cancelar reservas”, the script reruns, and unless you track that the dialog should be open, it won’t be called again, so it closes instantly. This is a common source of confusion and is discussed in the docs and forum posts.

To fix this, set a flag in st.session_state when the cancel button is pressed, and only call confirmation_window() when that flag is True. Then, after the dialog is handled (either “Sim” or “Não”), reset the flag and rerun. Here’s a minimal pattern:

if "show_confirm_dialog" not in st.session_state:
    st.session_state.show_confirm_dialog = False

if st.button("Cancelar reservas", type="primary"):
    if selecionados == []:
        st.error("Nenhuma reserva selecionada")
    else:
        st.session_state.show_confirm_dialog = True
        st.rerun()

if st.session_state.show_confirm_dialog:
    @st.dialog("Confirma o cancelamento?")
    def confirmation_window():
        confirmacao = st.columns(2)
        with confirmacao[0]:
            if st.button("Sim", type="primary"):
                cancelar()
                st.session_state.show_confirm_dialog = False
                st.rerun()
        with confirmacao[1]:
            if st.button("Não", type="primary"):
                st.session_state.show_confirm_dialog = False
                st.rerun()
    confirmation_window()

This ensures the dialog stays open until the user clicks a button. For more details, see Streamlit dialog docs and forum discussions.

Sources: