Skip to content

[Bug] BrushTool causes errors when segmentation is deleted while tool is active #2549

@lirl-cn

Description

@lirl-cn

Describe the Bug

When a segmentation is deleted while a brush tool (e.g., CircularBrush, SphereBrush) is active, subsequent mouse interactions with the viewport cause uncaught errors. This occurs because the brush tool's internal state and event handlers continue to reference the deleted segmentation data.

I attempted several workarounds at the application level, none of which fully resolved the issue:

  1. toolGroup.setToolDisabled(toolName) - Does not immediately remove already-bound DOM event listeners
  2. toolGroup.setToolActive('WindowLevel', ...) - The brush tool's internal state persists
  3. Calling tool.rejectPreview() - Does not clear all internal references
  4. Dispatching synthetic ESC key event - Tool does not respond to programmatic key events
  5. Using setTimeout to defer deletion - Events still fire on the deleted data
    The BrushTool maintains internal state that references segmentation data:
  • Preview data for in-progress strokes
  • References to the active segmentation's labelmap
    When segmentationService.remove() is called, this internal state is not cleared. When the user subsequently interacts with the canvas:
  1. _onMouseUp event fires
  2. BrushTool._endCallback is called
  3. BrushStrategy.acceptPreview attempts to iterate over data that no longer exists

Option 1: Defensive checks in BrushStrategy
Add null/undefined checks in BrushStrategy.acceptPreview and other methods that access segmentation data.
Option 2: Subscribe to segmentation removal events
The brush tool could subscribe to segmentation removal events and automatically clear its internal state when the associated segmentation is deleted.
Option 3: Enhanced setToolDisabled behavior
When setToolDisabled is called, it should:

  • Clear any in-progress operations
  • Remove pending event handlers
  • Reset internal state

Steps to Reproduce

1.Create a new segmentation
2.Select a brush tool (e.g., CircularBrush)
3.Draw on the canvas (optional, but makes it more reproducible)
4.Delete the segmentation (via UI or programmatically calling segmentationService.remove())
5.Click on the canvas

The current behavior

Uncaught TypeError: Cannot read properties of undefined (reading 'forEach')
at BrushStrategy.acceptPreview
at ToolInstance.acceptPreview
at ToolInstance.applyActiveStrategyCallback
at ToolInstance.acceptPreview
at BrushTool._endCallback
at triggerEvent
at _onMouseUp

The expected behavior

he brush tool should gracefully handle the case where its associated segmentation has been deleted. Either:

  • The tool should be automatically deactivated when the segmentation is deleted
  • The tool should have defensive checks to prevent accessing undefined data
  • The tool should clear its internal state when segmentation data is removed

System Information

System:
OS: macOS 15.6.1
CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
Memory: 189.44 MB / 64.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.18.0 - /usr/local/bin/node
Yarn: 1.22.22 - ~/.yarn/bin/yarn
npm: 10.9.3 - /usr/local/bin/npm
Browsers:
Chrome: 143.0.7499.193
Firefox: 146.0.1
Safari: 26.1

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions