Bad 'setIn' index : Issue with using fragments that do not render anything within multipage app

Hi! I am building a multipage website which mainly involves updating a dashboard from live data which I poll periodically. To manage my polling functions, I have placed them into individual st.fragment components which runs at a set interval. These components do not contain any rendering functions, and are purely computational. These components are placed into a common module which I import into my different pages.

I noticed that when I use the same fragment across two different pages, and navigate from one to another, I often get an error where the page either does not load (permanent skeleton loading state), or I get a Bad message format 'setIn' cannot be called on an ElementNode error or something along the lines of Bad 'setIn' index.

Not sure if it is related, but this seems to occur more often if I have widgets rendered inside columns on the page.

Using this approach, I was able to effectively achieve my desired dashboard look on one page, but once I made it into a multipage app, it became very buggy and crashes very often to the point where it is not usable. I am really hoping someone can provide some insight into this problem, or suggest a better approach for such live data polling use cases.

I cannot share my repository, but this is a very minimal reproduction of the app, in which I have verified the issue still exists:

Streamlit version: 1.38.0
Python version: 3.11
Environment: Local

File directory:

  • main.py
  • functions.py
  • pages
    • try.py

main.py:

import streamlit as st
import functions

st.text("hi!")
functions.do_something()

functions.py:

import streamlit as st
@st.fragment(run_every="0.5s")
def do_something():
    count = 0
    for i in range(2000):
        count += i

try.py

import streamlit as st
import functions


functions.do_something()

c1, c2 = st.columns(2)
with c1:
    st.text("hmm")
with c2:
    st.text("hi")

The issue occurs less often with this reproduction as it is really minimal, but if you toggle between the two pages quickly enough the problem is bound to happen.

Would really appreciate if someone could help me with this!

Hi @confusedbird,

Sorry, I tried reproducing that error with the script you shared, and couldn’t get the error to show up. Is there anything else that you can add to make it more reproducible?

Hi! Thank you so much for your response.

I have made a slight edit to main.py:

import streamlit as st
import functions

st.text("hi!")
st.button("Random button")

functions.do_something()

By adding a button, the problem happens alot more frequently already, at least on my side. It becomes even more apparent when I add more and bigger components such as a st_folium map. I have tested on both Edge and Chrome. To reproduce the problem, you can quickly toggle between the two pages using the sidebar.

I have some issues with screen recording, but this is a screenshot of the problem with the exact same code:

Thank you so much!

1 Like

I’m so sorry, but I’m still not able to reproduce it :frowning:

I tried adding 1000 buttons instead, but still I don’t see that error.

What OS is this on?

Hi, thank you so much for trying! I really appreciate it.

I have edited main.py to such:

import streamlit as st

import functions

st.text("hi!")

c1, c2 = st.columns(2)
with c1:
    for i in range(100):
        st.button("help", key=i)

with c2:
    st.text("hi")
    functions.do_something()

and functions.py to:

import streamlit as st


@st.fragment(run_every="0.5s")
def do_something():
    count = 0
    for i in range(200000):
        count += i

Here is a screen recording showing how I encounter the issue, and the console log of the browser.

streamlit_help.mov [video-to-gif output image]

The current example seems a little ridiculous :sweat_smile:, but the multipage app that I am building has many pages and fragments like such, and the issue occurs very often even when I am just slowly navigating from one page to another.

Previously, I was on Windows, but I tried it on Mac and was able to replicate it too (this video was recorded on Mac).

Thank you in advance!

1 Like

Hooray! I was able to reproduce the issue by shortening the time to 0.1s :slight_smile: I’ll check around and see if anybody has any ideas.

2 Likes

One of our engineers (@Benjamin5) tracked down what seems to be the issue, and has a fix for it [Fix] Clear fragment autoreruns when changing pages by raethlein · Pull Request #9617 · streamlit/streamlit · GitHub

Could you test this out by pip installing this whl? https://core-previews.s3-us-west-2.amazonaws.com/pr-9617/streamlit-1.39.0-py2.py3-none-any.whl

I installed it, and it seemed to resolve the issue for me, but please let me know if you still see the error.

1 Like

Thank you @blackary and @Benjamin5 ! I have verified that this indeed solves the problem on my original app! I am so grateful to the both of you. :grinning:

However, I noticed thatst.set_page_config no longer applies to the pages in the multipage app.

Since the last time I posted, I have changed my multipage approach from using pages/ directory to using st.navigation as the documentation suggests. I was able to successfuly set the page config to wide on my entry file and have it apply to the rest of the pages prior to this fix version, but once I installed the fix, I notice that the pages start off wide, but default to the normal after a second or so. I then uninstalled the fix and I do not notice this issue anymore. This also seems to only happen on pages where there are fragments with a rerun interval. Perhaps there is some unintended consequences to the fix?

Here is a minimal reproduction:

File directory:
entry.py
main.py
try.py

entry.py:

import streamlit as st

def main():

    main_page = st.Page("main.py", title="Main")
    help_page = st.Page("try.py", title="Help")

    pg = st.navigation([main_page, help_page])
    pg.run()

if __name__ == "__main__":
    st.set_page_config(layout="wide")

main()

main.py:

import streamlit as st

import functions

st.text("hi!")

c1, c2, c3 = st.columns(3)
with c1:
    for i in range(100):
        st.button("help", key=i)

with c2:
    st.text("hi")
    functions.do_something()

with c3:
    st.button("hello")

try.py:

import streamlit as st
import functions



c1, c2 = st.columns(2)
with c1:
    st.text("hmm")
with c2:
    st.text("hi")


functions.do_something()

Here is a picture of how the same code looks like, after the fix (top) and before the fix (bottom).

Thank you once again for the help!

Hey @confusedbird , I have just had a look and I think the behavior is unrelated to the fix itself. But the fix is applied on top of the current develop branch and I believe this behavior you reported in the last comment changed in PR [Fix] MPA page layout by sfc-gh-pchiu · Pull Request #9479 · streamlit/streamlit · GitHub that was merged into develop 4 days ago.
@eric.c @kmcgrady Could you please have a look at the latest reported issue with regards to the wide mode? Maybe its expected behavior and there is some best practice.

2 Likes

Hi @confusedbird!
Thank you for your patience. I just want to share that we were able to repro the issue with layout changing away from the wide config.
After investigating with @raethlein and @kmcgrady, we have a proposed fix WIP. You could use this .whl file to test on your end in the meantime.

2 Likes