Skip to content

Conversation

Copy link

Copilot AI commented Oct 30, 2025

geemap crashes when used with Solara due to premature widget serialization during Toolbar initialization. Setting main_tools and extra_tools traits (which have sync=True with widget_serialization) triggers immediate serialization before initialization completes, causing the error in ipywidgets' _widget_to_json.

Changes

Wrapped trait assignments in hold_trait_notifications() context manager in Toolbar.__init__():

# Before: immediate notification on each assignment
self.main_tools = main_tools + ([self.toggle_widget] if extra_tools else [])
self.extra_tools = extra_tools

# After: batch notifications after both assignments complete
with self.hold_trait_notifications():
    self.main_tools = main_tools + ([self.toggle_widget] if extra_tools else [])
    self.extra_tools = extra_tools

This follows the traitlets recommended pattern for multiple trait assignments during initialization, ensuring all widgets are in a consistent state before serialization occurs.

Original prompt

This section details on the original issue you should resolve

<issue_title>geemap not working with Solara</issue_title>
<issue_description>Web App: https://huggingface.co/spaces/giswqs/solara-geemap

How to reproduce it:

git clone https://huggingface.co/spaces/giswqs/solara-geemap
pip install -r requirements.txt
solara run ./pages/

raceback (most recent call last):
File "/opt/conda/lib/python3.11/site-packages/reacton/core.py", line 392, in _create_widget
widget = self.component.widget(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jovyan/pages/02_inspector.py", line 9, in init
super().init(**kwargs)
File "/opt/conda/lib/python3.11/site-packages/geemap/geemap.py", line 158, in init
super().init(**kwargs)
File "/opt/conda/lib/python3.11/site-packages/geemap/core.py", line 749, in init
self.add(widget, position=position)
File "/opt/conda/lib/python3.11/site-packages/geemap/geemap.py", line 363, in add
super().add(obj, position=position, **kwargs)
File "/opt/conda/lib/python3.11/site-packages/geemap/core.py", line 940, in add
self._add_toolbar(position, **kwargs)
File "/opt/conda/lib/python3.11/site-packages/geemap/core.py", line 985, in _add_toolbar
toolbar_val = toolbar.Toolbar(
^^^^^^^^^^^^^^^^
File "/opt/conda/lib/python3.11/site-packages/geemap/toolbar.py", line 130, in init
self.main_tools = main_tools + ([self.toggle_widget] if extra_tools else [])
^^^^^^^^^^^^^^^
File "/opt/conda/lib/python3.11/site-packages/traitlets/traitlets.py", line 748, in set
self.set(obj, value)
File "/opt/conda/lib/python3.11/site-packages/traitlets/traitlets.py", line 737, in set
obj._notify_trait(self.name, old_value, new_value)
File "/opt/conda/lib/python3.11/site-packages/traitlets/traitlets.py", line 1532, in _notify_trait
self.notify_change(
File "/opt/conda/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 700, in notify_change
self.send_state(key=name)
File "/opt/conda/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 578, in send_state
state = self.get_state(key=key)
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/conda/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 615, in get_state
value = to_json(getattr(self, k), self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/conda/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 52, in _widget_to_json
return [_widget_to_json(v, obj) for v in x]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/conda/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 52, in
return [_widget_to_json(v, obj) for v in x]
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/conda/lib/python3.11/site-packages/ipywidgets/widgets/widget.py", line 54, in widget_to_json
return "IPY_MODEL
" + x.model_id
^^^^^^^^^^
File "/opt/conda/lib/python3.11/site-packages/solara/server/patch.py", line 539, in model_id_debug
raise RuntimeError(f"Widget {type(self)} has been closed, the stacktrace when the widget was closed is:\n{closed_stack[id(self)]}")
RuntimeError: Widget <class 'geemap.toolbar.ToolbarItem'> has been closed, the stacktrace when the widget was closed is:
File "/opt/conda/bin/solara", line 8, in
sys.exit(main())
File "/opt/conda/lib/python3.11/site-packages/solara/main.py", line 761, in main
cli(args[1:])
File "/opt/conda/lib/python3.11/site-packages/rich_click/rich_command.py", line 402, in call
return super().call(*args, **kwargs)
File "/opt/conda/lib/python3.11/site-packages/click/core.py", line 1462, in call
return self.main(*args, **kwargs)
File "/opt/conda/lib/python3.11/site-packages/rich_click/rich_command.py", line 216, in main
rv = self.invoke(ctx)
File "/opt/conda/lib/python3.11/site-packages/click/core.py", line 1850, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/opt/conda/lib/python3.11/site-packages/click/core.py", line 1246, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/opt/conda/lib/python3.11/site-packages/click/core.py", line 814, in invoke
return callback(*args, **kwargs)
File "/opt/conda/lib/python3.11/site-packages/solara/main.py", line 485, in run
start_server()
File "/opt/conda/lib/python3.11/site-packages/solara/main.py", line 451, in start_server
server.run()
File "/opt/conda/lib/python3.11/site-packages/uvicorn/server.py", line 67, in run
return asyncio_run(self.serve(sockets=sockets), loop_factory=self.config.get_loop_factory())
File "/opt/conda/lib/python3.11/site-packages/uvicorn/_compat.py", line 30, in asyncio_run
return runner.run(main)
File "/opt/conda/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
File "/opt/conda/lib/python3.11/asyncio/base_event...


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Use hold_trait_notifications() context manager to batch trait updates during
Toolbar.__init__() to prevent premature widget serialization that causes
errors in Solara environment.

Co-authored-by: giswqs <[email protected]>
Copilot AI changed the title [WIP] Fix geemap not working with Solara Fix Toolbar initialization to prevent widget serialization crash in Solara Oct 30, 2025
Copilot AI requested a review from giswqs October 30, 2025 16:29
Copilot finished work on behalf of giswqs October 30, 2025 16:29
self.main_tools = main_tools + ([self.toggle_widget] if extra_tools else [])
self.extra_tools = extra_tools
# Use hold_trait_notifications to avoid triggering widget serialization
# during initialization, which can cause issues in Solara and other environments
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Add . at the end of sentence.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added .

@giswqs giswqs marked this pull request as ready for review October 30, 2025 17:16
@giswqs giswqs requested review from Copilot and naschmitz October 30, 2025 17:16
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR addresses widget serialization issues during toolbar initialization in environments like Solara. The change wraps the assignment of main_tools and extra_tools attributes within a hold_trait_notifications() context manager to prevent premature trait notifications that could trigger serialization problems.

  • Wraps main_tools and extra_tools assignment in hold_trait_notifications() context
  • Adds explanatory comment about the serialization issue prevention
  • Maintains existing initialization logic while deferring trait notifications

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link

github-actions bot commented Oct 30, 2025

@github-actions github-actions bot temporarily deployed to pull request October 30, 2025 17:22 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

geemap not working with Solara

3 participants