HumanSignal/label-studio · error · ValidationError
Task[{key}] must be {class_def}
Error message
Task[{key}] must be {class_def} What it means
TaskValidator.raise_if_wrong_class enforces that optional task-root fields have specific Python types: 'data' must be dict or list, 'annotations' a list, 'predictions' a list, 'meta' a dict or list. If the key is present with the wrong type, this ValidationError names the required class (joined with ' or ' for tuples).
Source
Thrown at label_studio/tasks/validation.py:131
raise ValidationError(e.detail[0] + ' [assume: item["data"] = task root with values]')
@staticmethod
def check_allowed(task):
# task is required
if 'data' not in task:
return False
# everything is ok
return True
@staticmethod
def raise_if_wrong_class(task, key, class_def):
if key in task and not isinstance(task[key], class_def):
if isinstance(class_def, tuple):
class_def = ' or '.join([c.__name__ for c in class_def])
else:
class_def = class_def.__name__
raise ValidationError('Task[{key}] must be {class_def}'.format(key=key, class_def=class_def))
def validate(self, task):
"""Validate whole task with task['data'] and task['annotations']. task['predictions']"""
# task is class
if hasattr(task, 'data'):
self.check_data_and_root(self.project, task.data)
return task
# self.instance is loaded by get_object of view
if self.instance and hasattr(self.instance, 'data'):
if isinstance(self.instance.data, dict):
data = self.instance.data
elif isinstance(self.instance.data, str):
try:
data = json.loads(self.instance.data)
except ValueError as e:
raise ValidationError("Can't parse task data: " + extract_message(e))
else:View on GitHub (pinned to 0b49e9b539)
Solutions
- Ensure task['data'] is a dict (or list), task['annotations'] and task['predictions'] are lists, task['meta'] is a dict or list
- Parse stringified JSON before submission (json.loads the data string) so 'data' is a real dict
- Move a single annotation/prediction into a one-element list: [prediction]
- Pre-validate the task root shape before calling the API
Example fix
// before
{'data': '{"text": "hi"}', 'predictions': {'result': []}}
// after
{'data': {'text': 'hi'}, 'predictions': [{'result': []}]} Defensive patterns
Strategy: type-guard
Validate before calling
def check_root_shape(task):
assert 'data' not in task or isinstance(task['data'], (dict, list))
assert 'annotations' not in task or isinstance(task['annotations'], list)
assert 'predictions' not in task or isinstance(task['predictions'], list)
assert 'meta' not in task or isinstance(task['meta'], (dict, list)) Type guard
def task_root_ok(task):
return (isinstance(task, dict)
and (not isinstance(task.get('data'), str))
and isinstance(task.get('annotations', []), list)
and isinstance(task.get('predictions', []), list)) Try / catch
try:
import_tasks(tasks)
except ValidationError as e:
m = re.search(r'Task\[(\w+)\] must be ([\w or ]+)', str(e.detail[0]))
if m:
coerce_task_field(tasks, m.group(1), m.group(2)) Prevention
- json.loads any stringified data before submission
- Always send annotations/predictions as arrays, even for single items
- Keep 'meta' as a dict; don't overload 'predictions' for status strings
When it happens
Trigger: validate() calling raise_if_wrong_class with e.g. {'data': 'not-a-dict'}, {'annotations': {'result': []}} (dict instead of list), or {'predictions': 'pending'}.
Common situations: Putting pre-annotations under 'annotations' as a dict instead of a list of annotation objects; string-encoded JSON left in 'data' instead of a parsed dict; sending 'predictions' as a single object rather than an array.
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
- Task root must be dict with "data", "meta", "annotations", "
- Import data contains completed_by={completed_by} which is no
- data['{data_key}']={data_value} is of type '{type}', but the
- Field "data" must be string or dict, but not "{type(self.ins
- "result" field in annotation must be list
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/eb208297570b41d4.
Report an issue: GitHub.