HumanSignal/label-studio · error · StateManagerError
No state model found for {entity._meta.model_name} when tran
Error message
No state model found for {entity._meta.model_name} when transitioning state What it means
transition_state first checks whether FSM is disabled via CurrentContext.is_fsm_disabled() (silently succeeding), then resolves the entity's state model; if the registry has none, it raises StateManagerError noting the model can't be transitioned. Transitions can only be recorded through a registered state model, so transitioning an unregistered entity type is refused rather than silently ignored.
Source
Thrown at label_studio/fsm/state_manager.py:271
entity=task,
new_state='IN_PROGRESS',
transition_name='start_annotation',
user=request.user,
organization_id=request.user.active_organization_id,
context={'assignment_id': assignment.id},
reason='User started annotation work'
)
"""
if not cls._is_fsm_enabled(user=user):
return True # Feature disabled, silently succeed
# Skip if FSM is temporarily disabled (e.g., during cleanup or bulk operations)
if CurrentContext.is_fsm_disabled():
return True # FSM disabled, silently succeed
state_model = get_state_model_for_entity(entity)
if not state_model:
raise StateManagerError(f'No state model found for {entity._meta.model_name} when transitioning state')
current_state = cls.get_current_state_value(entity)
# Prevent same-state transitions - only create state records for actual state changes
# This avoids creating redundant data when the effective state doesn't change
# However, allow forced state records for audit trails (e.g., annotation updates)
# IMPORTANT: Also check if a state record exists in DB - if not, we must create one
# even if inferred state matches target state (to persist the inferred state)
if current_state == new_state and not force_state_record:
# Verify a state record actually exists in DB (not just inferred)
state_record_exists = state_model.objects.filter(**{entity._meta.model_name: entity}).exists()
if state_record_exists:
return True # Skip transition - record exists and state unchanged
# else: No record exists (state was inferred), continue to create record
# Optimistic concurrency control using cache-based locking
cache_key = cls.get_cache_key(entity)
lock_key = f'{cache_key}:lock'View on GitHub (pinned to 0b49e9b539)
Solutions
- Register a state model for the entity, or route the change through a registered transition instead of raw transition_state.
- Guard the call: only invoke transition_state when get_state_model_for_entity(entity) returns a model.
- Audit signal handlers/bulk-update code so they filter to FSM-managed models before calling transition_state.
- If it should be a silent no-op, use the CurrentContext FSM-disable mechanism (is_fsm_disabled path) around non-FSM bulk operations.
Example fix
// before
@receiver(post_save, sender=MyModel)
def on_save(sender, instance, **kwargs):
StateManager.transition_state(instance, 'updated') # raises for unregistered model
// after
@receiver(post_save, sender=MyModel)
def on_save(sender, instance, **kwargs):
if get_state_model_for_entity(instance):
StateManager.transition_state(instance, 'updated') Defensive patterns
Strategy: validation
Validate before calling
from fsm.registry import get_state_model_for_entity
from core.current_request import CurrentContext
if CurrentContext.is_fsm_disabled() or get_state_model_for_entity(entity) is None:
return True # nothing to transition; mirror the manager's silent-skip path Type guard
def can_transition(entity) -> bool:
from fsm.registry import get_state_model_for_entity
return get_state_model_for_entity(entity) is not None Try / catch
from fsm.state_manager import StateManager, StateManagerError
try:
StateManager.transition_state(entity, new_state, user=user)
except StateManagerError as e:
if 'No state model found' in str(e):
logger.info('skipping transition for unregistered model %s', entity._meta.model_name)
else:
raise Prevention
- Filter signal handlers and bulk jobs to FSM-registered models only
- Route state changes through registered transitions rather than raw transition_state calls
- Use the FSM-disable context for bulk operations on mixed entity types
When it happens
Trigger: Calling StateManager.transition_state(entity, new_state, ...) with an entity whose model is absent from the state-model registry — custom code invoking transitions directly, signal handlers on models without FSM registration, or post-save hooks firing for entity types never onboarded to the FSM.
Common situations: Adding a signal handler that transitions state for every save and then firing it for a non-FSM model; renaming a model so the registry key no longer matches; running custom scripts/management commands against models registered only in the enterprise edition.
Related errors
- No state model found for {entity._meta.model_name} when gett
- No state model found for {entity._meta.model_name} when gett
- No state model registered for {entity._meta.model_name} when
- Invalid entity name: {entity_name}
- transition_name: Unknown transition for this entity
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/cfa47c7149ed2a6b.
Report an issue: GitHub.