Removing an item from multi select

I am trying to delete objects from a list by choosing them via a multiselect widget. However, after the app reruns I get the error: streamlit.errors.StreamlitAPIException: Every Multiselect default value must exist in options

if st.button("Fill") or "options" not in st.session_state:
	st.session_state.options=["a","b","c"]

def submit():
	for item in st.session_state.selected:
		st.session_state.options.remove(item)

form=st.form("My form")
form.multiselect("Select", st.session_state.options, key="selected")
form.form_submit_button("Submit", on_click=submit)

I tried to add the line
st.session_state.selected=[]
to the submit function so that the multiselect-box is cleared and does not reference deleted items, but it did not solve the issue.

The error message looks like this:

Exception in thread ScriptRunner.scriptThread:
Traceback (most recent call last):
  File "/Users/arc/opt/anaconda3/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/Users/arc/opt/anaconda3/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/arc/opt/anaconda3/lib/python3.8/site-packages/streamlit/script_runner.py", line 182, in _process_request_queue
    widget_states = self._session_state.as_widget_states()
  File "/Users/arc/opt/anaconda3/lib/python3.8/site-packages/streamlit/state/session_state.py", line 447, in as_widget_states
    return self._new_widget_state.as_widget_states()
  File "/Users/arc/opt/anaconda3/lib/python3.8/site-packages/streamlit/state/session_state.py", line 198, in as_widget_states
    states = [
  File "/Users/arc/opt/anaconda3/lib/python3.8/site-packages/streamlit/state/session_state.py", line 201, in <listcomp>
    if self.get_serialized(widget_id)
  File "/Users/arc/opt/anaconda3/lib/python3.8/site-packages/streamlit/state/session_state.py", line 179, in get_serialized
    serialized = metadata.serializer(item.value)
  File "/Users/arc/opt/anaconda3/lib/python3.8/site-packages/streamlit/elements/multiselect.py", line 139, in serialize_multiselect
    return _check_and_convert_to_indices(opt, value)
  File "/Users/arc/opt/anaconda3/lib/python3.8/site-packages/streamlit/elements/multiselect.py", line 118, in _check_and_convert_to_indices
    raise StreamlitAPIException(
streamlit.errors.StreamlitAPIException: Every Multiselect default value must exist in options

Thanks for any help in advance! :slight_smile:

2 Likes

Hi @arc, and welcome to the Streamlit community! :balloon:

Can you please try without the state element? Does it get rid of the issue?

Thanks
Charly

Hi @Charly_Wargnier. Thank you for the response.

I am not sure what you mean. If you mean making the list options into a normal variable instead of an entry of the session_state dictionary then this doesn’t really work as the list would stay the same after pressing the submit button as the script gets run from top to bottom again. I want to be able to change the list via selecting specific entries to remove.

Looping @snehankekre as he may be more familiar with this State scenario? :arrow_down:

Thanks,
Charly

Additional Info:
Turns out if you delete the widget (not the options list) from the session state each time when the app is loaded I get the behavior I intend—if I select “a” and click on “submit” the options in the next iteration are only “b” and “c” and the list is changed. However, this seems to be more of a hack than a nice fix. I think this problem might be due to missing functionality/a bug in the library?

if "selected" in st.session_state:
    del st.session_state.selected

Thanks for your feedback @arc

Let me liaise with Devs on this.

Best,
Charly

Hey @arc, thanks for bringing this to our attention. I have looked into this a bit, and it is caused by the interactions of several things not being designed for this kind of use.

Before session state, arguments to widgets, and values received by widgets, were somewhat less dynamic, so our input validation did a fine job of catching problems right away. But now with state, scripts are doing a lot more interesting things we didn’t always design for.

In this case, the implementation detail that we track options in a multiselect using indices is leaking out, as the changing options argument means the indices no longer track the values correctly. Additionally, the widget argument validation is aimed towards making sure the basic use case of [select some values, and make them available as data for the rest of the app] works well, and it doesn’t try to account for the options changing.

In fact, before session state, changing the options would automatically reset the widget state as it would be seen as a new widget, and it was only with session state that keyed widgets had a sufficiently persistent identity that this could be an issue. That said, the question of how to handle the state of widgets whose arguments have changed is one we have long wanted to revisit, since there is a lot of room for making widgets try to update their state to conform to changed arguments.

The workaround of deleting the widget works because clearing the widget state prevents the old indices, which no longer mean the right thing, from sticking around and doing weird stuff.

The behavior you are currently experiencing is definitely not right, and I will open an issue for it, though it may take a bit to fix since there are so many factors in play and changing them could have big ripple effects that we will need to think through carefully.

4 Likes

Hey @AnOctopus. Thanks for your answer. I am looking forward for the functionality to be updated. For completeness, I am also linking my post about similar problems with the select box widget: Dependency Between Selectbox and a Changing List - #2 by Charly_Wargnier

1 Like