HumanSignal/label-studio · error · ValidationError
detail: {pydantic validation message}
Error message
detail: {pydantic validation message} What it means
When FSMEntityTransitionAPI.post executes a transition, the transition's payload is instantiated against a pydantic schema. If that instantiation raises pydantic's ValidationError, the API converts it into a DRF 400 ValidationError with the message extracted by extract_message. This is a request-payload shape/type failure for the transition_data you supplied, not an internal failure.
Source
Thrown at label_studio/fsm/api.py:186
triggers_on_update = getattr(transition_class, '_triggers_on_update', False)
if triggers_on_create or triggers_on_update:
raise ValidationError(
{'transition_name': ['Transition is auto-triggered and cannot be executed manually']}
)
# Execute transition
StateManager = get_state_manager()
try:
state_record = StateManager.execute_transition(
entity=entity,
transition_name=transition_name,
transition_data=transition_data,
user=request.user,
organization_id=getattr(request.user, 'active_organization_id', None),
)
except PydanticValidationError as e:
# Pydantic schema validation errors from transition instantiation
raise ValidationError({'detail': extract_message(e)})
except TransitionValidationError as e:
# Explicit validation failure
logger.warning(
f'Transition validation failed with context: {e.context} and error: {e} for entity: {entity.id}'
)
raise ValidationError({'detail': extract_message(e)})
# Handle feature-flag disabled path (no state record created)
if state_record is None:
response_payload = {
'success': True,
'new_state': None,
'state_record': None,
}
else:
response_payload = {
'success': True,
'new_state': state_record.state,
# Pass model instance; nested serializer will handle representationView on GitHub (pinned to 0b49e9b539)
Solutions
- Read the returned pydantic message and fix transition_data to match the transition's pydantic schema (correct keys, types, required fields).
- Inspect the transition class's pydantic model in the code to see the exact expected payload shape.
- Validate the payload client-side with the same pydantic model (or its JSON schema) before calling the API.
- Check for a version mismatch where the deployed transition schema is newer than the client; update the client payload accordingly.
Example fix
// before (400: 'transition_data.comment: field required')
{"transition_name": "reject_annotation", "transition_data": {"reason": "bad"}}
// after
{"transition_name": "reject_annotation", "transition_data": {"comment": "bad label", "reason": "bad"}} Defensive patterns
Strategy: validation
Validate before calling
from fsm.registry import transition_registry
transition_class = transition_registry.get_transition(entity_name, transition_name)
validated = transition_class.InputSchema(**transition_data) # raises locally, same message pydantic would give
payload = {'transition_name': transition_name, 'transition_data': validated.model_dump()} Type guard
def has_valid_transition_data(transition_class, transition_data: dict) -> bool:
schema = getattr(transition_class, 'InputSchema', None) or getattr(transition_class, 'input_schema', None)
if schema is None:
return True
try:
schema(**transition_data)
return True
except Exception:
return False Try / catch
try:
resp = client.execute_transition(entity_type, entity_id, transition_name, transition_data)
except Exception as e:
if 'detail' in str(e): # pydantic message surfaced by the API
logger.error('invalid transition_data for %s: %s', transition_name, e)
raise Prevention
- Validate payloads against the transition's pydantic schema client-side before calling the API
- Generate request payloads from the schema (JSON schema / model_dump), not hand-written dicts
- Keep client schema copies in sync when transition models change
When it happens
Trigger: POSTing to the FSM transition endpoint where transition_data does not match the transition class's pydantic input schema: missing required fields, wrong types, extra fields when extra="forbid", or values failing field constraints.
Common situations: Sending flat fields instead of the nested transition_data object; passing string values where pydantic expects int/enum; after upgrading, the transition schema gained a new required field that older clients don't send; typos in transition_data keys.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- transition_name: Unknown transition for this entity
- transition_name: Transition is auto-triggered and cannot be
- detail: {transition validation message}
- sample() does not accept arguments.
- random(min, max) requires two arguments.
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/d12389b345deefdb.
Report an issue: GitHub.