Fragments cannot write widgets to outside containers - Expected behavior?

I’ve recently started using fragments to speed up viz on my apps and wondering why I can’t put a button in a column within a fragment function. This seems like a bug since the error message (see below) isn’t exactly in line with the issue, as I am not trying to write to an outside container

If I run this code, I get the error:

import streamlit as st


def _set_state():
    st.session_state.test = True


@st.fragment
def _fragment_test():
    button_cols = st.sidebar.columns(2)
    with button_cols[0]:
        st.button("Test", on_click=_set_state)
    if 'test' in st.session_state and st.session_state.test:
        st.write("Test is True")


def main():
    _fragment_test()


if __name__ == "__main__":
    main()

However, I can run similar code without the columns with no problem (just showing the updated _fragment_test for brevity, everything else is the same):

@st.fragment
def _fragment_test():
    st.button("Test", on_click=_set_state)
    if 'test' in st.session_state and st.session_state.test:
        st.write("Test is True")

The test version is deployed on streamlit.io: https://testappfragmentcallback-igb9jmucogwpr9mx48i8ug.streamlit.app/

GitHub: https://github.com/msquaredds/TestStreamlitFragmentCallback/

Error Message from test:

streamlit.errors.StreamlitFragmentWidgetsNotAllowedOutsideError : This app has encountered an error. The original error message is redacted to prevent data leaks. Full error details have been recorded in the logs (if you’re on Streamlit Cloud, click on ‘Manage app’ in the lower right of your app).
Traceback:

File "/mount/src/teststreamlitfragmentcallback/main.py", line 12, in _fragment_test
    st.button("Test", on_click=_set_state)File "/home/adminuser/venv/lib/python3.12/site-packages/streamlit/runtime/metrics_util.py", line 410, in wrapped_func
    result = non_optional_func(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "/home/adminuser/venv/lib/python3.12/site-packages/streamlit/elements/widgets/button.py", line 243, in button
    return self.dg._button(
           ^^^^^^^^^^^^^^^^File "/home/adminuser/venv/lib/python3.12/site-packages/streamlit/elements/widgets/button.py", line 914, in _button
    check_widget_policies(File "/home/adminuser/venv/lib/python3.12/site-packages/streamlit/elements/lib/policies.py", line 173, in check_widget_policies
    check_fragment_path_policy(dg)File "/home/adminuser/venv/lib/python3.12/site-packages/streamlit/elements/lib/policies.py", line 160, in check_fragment_path_policy
    raise StreamlitFragmentWidgetsNotAllowedOutsideError()

Btw, the error message in my full app is slightly different at the beginning and with a slightly better plain english explanation:

streamlit.errors.StreamlitFragmentWidgetsNotAllowedOutsideError : Fragments cannot write widgets to outside containers.

From the docs:

Calling st.sidebar in a fragment is not supported. To write elements to the sidebar with a fragment, call your fragment function inside a with st.sidebar context manager.

The sidebar counts as a container.

Oh, I missed that, got it - thanks!

Btw, do you know if there’s planned support for the sidebar? My use case is hitting a sidebar button, which updates viz in the main area, so the sidebar call would need to be within the fragment (without some sort of page re-design)

I can’t find anything in the roadmap. Your options are a page redesign or a full rerun (in most cases reruns can be made very fast).

1 Like

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