Skip to content

fix: BROS-849: Taxonomy is broken. Try 2#9622

Open
makseq wants to merge 1 commit intodevelopfrom
bros-849-2
Open

fix: BROS-849: Taxonomy is broken. Try 2#9622
makseq wants to merge 1 commit intodevelopfrom
bros-849-2

Conversation

@makseq
Copy link
Member

@makseq makseq commented Mar 16, 2026

Bug: Taxonomy breaks on first open after SPA navigation (no page reload)

What was broken

When a user creates a new project with a Taxonomy label config and opens Quick View (or the labeling interface) without a full page reload, the editor fails with:

Error: [mobx-state-tree] Cannot add an object to a state tree if it is already
part of the same or another state tree. Tried to assign an object to
'/annotationStore/sharedStores/taxonomy', but it lives already at
'/annotationStore/sharedStores/taxonomy'

The UI renders broken. A full page refresh fixes it — until the next new project.

Root cause

SharedChoiceStore (used by Taxonomy and Choices) maintains two module-level singletons that live for the lifetime of the browser tab:

export const Stores = new Map();   // SharedStoreModel instances
const StoreIds = new Set();        // IDs of already-created stores

These caches are intentional — they let multiple annotations on the same task share one store instance. But they are never cleared on SPA navigation.

When the user navigates to a new project without a reload:

  1. The old LSF instance is torn down, but Stores still holds the old SharedStoreModel instance for "taxonomy" — an instance that was previously attached to (and detached from) the old MST tree
  2. The new LSF initializes, calls initializeStoreafterReset() → tries to attach the same stale instance to the new tree
  3. MST sees the node as still "belonging" to another tree and throws

This was further aggravated by a performance optimization (PR #9495 / BROS-827) that wrapped resetState() and initializeStore() in the same runInAction() block. Within a single MobX transaction, detach() (called by beforeReset) doesn't commit before afterReset tries to re-attach the same stores — causing the same error even during normal task switching.

Fix (two changes)

1. lsf-sdk.js — split the runInAction batch

initializeStore is moved outside the runInAction block so detach() commits before afterReset() re-attaches shared stores:

// resetState + toggleInterface + assignTask batched together (safe)
runInAction(() => {
  this.lsf.resetState();
  this.lsf.toggleInterface(...);
  this.lsf.assignTask(task);
});

// initializeStore runs AFTER the transaction commits
this.lsf.initializeStore(lsfTask);

2. extender.js — defensive afterReset()

afterReset() now catches the MST error when a cached store instance is stale (still attached to a dead tree from a previous LSF lifecycle). On failure, it recreates the store from its snapshot and updates the global cache:

afterReset() {
  Stores.forEach((store, key) => {
    try {
      self.addSharedStore(store);
    } catch {
      // Stale instance from previous LSF lifecycle — recreate from snapshot
      const snapshot = safeGetSnapshot(store) ?? { id: key, children: [] };
      const freshStore = SharedStoreModel.create(snapshot);
      Stores.set(key, freshStore);
      self.addSharedStore(freshStore);
    }
  });
},

Fix 1 addresses task-switching. Fix 2 addresses first-open after SPA navigation. Together they cover all known paths to this error.

@netlify
Copy link

netlify bot commented Mar 16, 2026

Deploy Preview for heartex-docs canceled.

Name Link
🔨 Latest commit fb04614
🔍 Latest deploy log https://app.netlify.com/projects/heartex-docs/deploys/69b812f3b79fd30008814d6c

@netlify
Copy link

netlify bot commented Mar 16, 2026

Deploy Preview for label-studio-docs-new-theme canceled.

Name Link
🔨 Latest commit fb04614
🔍 Latest deploy log https://app.netlify.com/projects/label-studio-docs-new-theme/deploys/69b812f327b26f000837dbca

@github-actions github-actions bot added the fix label Mar 16, 2026
@netlify
Copy link

netlify bot commented Mar 16, 2026

Deploy Preview for label-studio-playground ready!

Name Link
🔨 Latest commit fb04614
🔍 Latest deploy log https://app.netlify.com/projects/label-studio-playground/deploys/69b812f3f5d62c0008ad8a87
😎 Deploy Preview https://deploy-preview-9622--label-studio-playground.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Mar 16, 2026

Deploy Preview for label-studio-storybook ready!

Name Link
🔨 Latest commit fb04614
🔍 Latest deploy log https://app.netlify.com/projects/label-studio-storybook/deploys/69b812f3084e930008c95d2c
😎 Deploy Preview https://deploy-preview-9622--label-studio-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov
Copy link

codecov bot commented Mar 16, 2026

Codecov Report

❌ Patch coverage is 9.09091% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...bs/editor/src/mixins/SharedChoiceStore/extender.js 9.09% 10 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant