HumanSignal / HumanSignal/label-studio
[Bug] Image not rendering due to mobx-state-tree action error in ImageEntity.js
- Dominant language
- TypeScript
- Stars
- 28.3k
- Forks
- 3.7k
- Avg merge
- 14h
- Merged PRs (30d)
- 15
Description
**Describe the bug**
Images are not rendering in the labeling interface. Network requests for image data succeed (200 OK), but the `` element is not generated. The browser console shows
mobx-state-tree error when the `setError` method attempts to modify state outside of an action context.
Console error:
Uncaught (in promise) Error: [mobx-state-tree] Cannot modify 'ImageEntity@/annotationStore/annotations/0/root/children/0/imageEntities/0(id: image#0@C17cO)', the object i protected and can only be modified by using an action.
at ImageEntity.js:238:20
**To Reproduce**
1. Go to a project with images stored in AWS S3
2. Click on a task to open the labeling interface
3. Observe that the image area is blank
4. Open browser DevTools → Console tab
5. See the mobx-state-tree error
**Expected behavior**
The image should be displayed in the labeling interface. If image loading fails, an error message should be shown without breaking the entire rendering process.
**Screenshots**
The `.lsf-image` container only contains a 1px canvas overlay, with no `` element:
```html
```
Environment (please complete the following information):
- OS: N/A (HumanSignal Cloud)
- Label Studio Version: HumanSignal Cloud (app.heartex.com) - latest as of 2026-02-03
- Storage: AWS S3
Additional context
Root Cause Identified
cc @bmartel
The bug was introduced in #6930 (merged 2025-01-27).
In ImageEntity.js, the img.onerror callback modifies mobx-state-tree state outside of an action context:
```typescript
img.onerror = () => {
self.setError(true); // ← This might be outside action context
self.setDownloading(false);
resolve();
};
```
Since onerror is an asynchronous callback, it may execute outside the original preload() action's context. In mobx-state-tree, modifying state outside of an action throws an exception, which could be interrupting the image rendering process.
Possible Fix (suggested by Claude)
Claude suggested that wrapping the state modifications in runInAction might resolve the issue:
```typescript
import { runInAction } from "mobx";
img.onerror = () => {
runInAction(() => {
self.setError(true);
self.setDownloading(false);
});
resolve();
};
```
I'm not entirely sure if this is the correct approach, so please let me know if there's a better solution.
Contributor guide
Assessment
This issue has not been assessed yet.