IndexError: pop index out of range in streamlit with from streamlit_dnd import dnd, apply_move

I have reviewed my code, and it runs correctly. However, when I attempt to move the container from col1 to col2, or vice versa, or if I move any container using the mouse to a different column, I encounter an error: IndexError: pop index out of range at the line of code apply_move(event, st.session_state). Please examine my code and the error, and provide a suitable solution along with the corrected code.

import streamlit as st

from streamlit_dnd import dnd, apply_move

import pandas as pd

st.set_page_config(layout=“wide”)

# Initialize 5 dataframes in session state

if “dfs” not in st.session_state:

st.session_state.dfs = {

    "df1": pd.DataFrame({"Data": \["Item A", "Item B"\]}),

    "df2": pd.DataFrame({"Data": \["Item C", "Item D"\]}),

    "df3": pd.DataFrame({"Data": \["Item E", "Item F"\]}),

    "df4": pd.DataFrame({"Data": \["Item G", "Item H"\]}),

    "df5": pd.DataFrame({"Data": \["Item I", "Item J"\]}),

}

if “mdfs” not in st.session_state:

st.session_state.mdfs = {

    "mdf1": pd.DataFrame({"Data": \["Item A", "Item B"\]}),

    "mdf2": pd.DataFrame({"Data": \["Item C", "Item D"\]}),

    "mdf3": pd.DataFrame({"Data": \["Item E", "Item F"\]}),

    "mdf4": pd.DataFrame({"Data": \["Item G", "Item H"\]}),

    "mdf5": pd.DataFrame({"Data": \["Item I", "Item J"\]}),

}

if “my_variable” not in st.session_state:

st.session_state\["my_variable"\] = "Initial Value"

# 2. Create columns

col1, col2 = st.columns(2 ,border=True)

# 3. Render containers in columns

with col1:

st.subheader("Right Column")

with st.container(border=True, key="right"):

    for df_key, df_val in st.session_state.dfs.items():

        with st.container(key=f"right\_{df_key}", border=True):

            st.write(f"### {df_key.upper()}")

            st.dataframe(df_val)

with col2:

st.subheader("mfaRight Column")

with st.container(border=True, key="mright"):

    for df_key, df_val in st.session_state.mdfs.items():

        with st.container(key=f"mright\_{df_key}", border=True):

            st.write(f"### {df_key.upper()}")

            st.dataframe(df_val)

# 4. Handle Drag and Drop

event = dnd(“right”, “mright”)

if event is not None:

apply_move(event, st.session_state)

st.rerun()

error :

IndexError: pop index out of range

File “D:\pyff\dndtry.py”, line 79, in
apply_move(event, st.session_state)
~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\user\AppData\Local\Programs\Python\Python314\Lib\site-packages\streamlit_dnd\_init_.py”, line 270, in apply_move
item = src.pop(event.from_index)

Hey there, thanks for sharing your code and the detailed error info! :balloon: It could be possible that the IndexError: pop index out of range is happening because the apply_move function from streamlit_dnd expects the containers you pass to dnd() to directly contain lists (or similar structures), but in your code, you’re passing the keys of containers that hold multiple DataFrames (dicts of DataFrames), not lists. When you try to move an item, the indices don’t match up with the underlying data structure, so pop fails.

Based on the streamlit-dnd demo and docs, you should use a list (not a dict of DataFrames) as the data source for each draggable container. The apply_move utility expects a list, so you should refactor your code to store your items as lists (e.g., a list of DataFrames or a list of strings), not as dicts. Here’s a minimal working example adapted from the official demo:

import streamlit as st
from streamlit_dnd import dnd, apply_move
import pandas as pd

st.set_page_config(layout="wide")

# Initialize lists of DataFrames in session state
if "dfs" not in st.session_state:
    st.session_state.dfs = [
        pd.DataFrame({"Data": ["Item A", "Item B"]}),
        pd.DataFrame({"Data": ["Item C", "Item D"]}),
    ]
if "mdfs" not in st.session_state:
    st.session_state.mdfs = [
        pd.DataFrame({"Data": ["Item E", "Item F"]}),
        pd.DataFrame({"Data": ["Item G", "Item H"]}),
    ]

col1, col2 = st.columns(2, border=True)

with col1:
    st.subheader("Right Column")
    with st.container(border=True, key="right"):
        for i, df in enumerate(st.session_state.dfs):
            with st.container(key=f"right_{i}", border=True):
                st.write(f"### DF {i+1}")
                st.dataframe(df)

with col2:
    st.subheader("mfaRight Column")
    with st.container(border=True, key="mright"):
        for i, df in enumerate(st.session_state.mdfs):
            with st.container(key=f"mright_{i}", border=True):
                st.write(f"### MDF {i+1}")
                st.dataframe(df)

event = dnd("right", "mright")
if event:
    # Combine both lists into a dict for apply_move
    lists = {"right": st.session_state.dfs, "mright": st.session_state.mdfs}
    apply_move(event, lists)
    st.session_state.dfs = lists["right"]
    st.session_state.mdfs = lists["mright"]
    st.rerun()

This approach should prevent the index error, as each container now holds a list, and apply_move can safely pop and insert items by index. If you need to keep track of DataFrame names, consider using a list of tuples or a list of dicts instead.

Sources: