HumanSignal/label-studio · error · ValidationError

"result" field in annotation must be list

Error message

"result" field in annotation must be list

What it means

TaskValidator.validate raises this when an annotation dict has a 'result' key but its value is not a list. The import format requires 'result' to be an array of labeling result objects; any other JSON type (string, dict, null, number) fails this check.

Source

Thrown at label_studio/tasks/validation.py:180

            # task[data]
            self.raise_if_wrong_class(task, 'data', (dict, list))
            self.check_data_and_root(self.project, task['data'])

            # task[annotations]: we can't use AnnotationSerializer for validation
            # because it's much different with validation we need here
            self.raise_if_wrong_class(task, 'annotations', list)
            for annotation in task.get('annotations', []):
                if not isinstance(annotation, dict):
                    logger.warning('Annotation must be dict, but "%s" found', str(type(annotation)))
                    continue

                ok = 'result' in annotation
                if not ok:
                    raise ValidationError('Annotation must have "result" fields')

                # check result is list
                if not isinstance(annotation.get('result', []), list):
                    raise ValidationError('"result" field in annotation must be list')

            # task[predictions]
            self.raise_if_wrong_class(task, 'predictions', list)
            for prediction in task.get('predictions', []):
                if not isinstance(prediction, dict):
                    logger.warning('Prediction must be dict, but "%s" found', str(type(prediction)))
                    continue

                ok = 'result' in prediction
                if not ok:
                    raise ValidationError('Prediction must have "result" fields')

            # task[meta]
            self.raise_if_wrong_class(task, 'meta', (dict, list))

        # task is data as is, validate task as data and move it to task['data']
        else:
            self.check_data_and_root(self.project, task, dict_is_root=True)

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Wrap the result value in a list: 'result': [result_obj]
  2. If result is a dict of multiple results, convert to a list of individual result objects
  3. Check the incoming JSON for result: null and replace with an empty list or drop the annotation
  4. Pre-validate with isinstance(a['result'], list) before POSTing

Example fix

// before
{"annotations": [{"result": {"type": "labels", "value": {"labels": ["A"]}}}]}
// after
{"annotations": [{"result": [{"type": "labels", "value": {"labels": ["A"]}}]}]}
Defensive patterns

Strategy: type-guard

Validate before calling

for task in tasks:
    for a in task.get('annotations', []):
        if isinstance(a, dict) and 'result' in a and not isinstance(a['result'], list):
            a['result'] = [a['result']] if a['result'] is not None else []

Type guard

def is_annotation(a):
    return isinstance(a, dict) and isinstance(a.get('result'), list)

Try / catch

try:
    client.import_tasks(id=project_id, tasks=tasks)
except LabelStudioError as e:
    if 'result" field in annotation must be list' in str(e):
        for t in tasks:
            for a in t.get('annotations', []):
                if 'result' in a and not isinstance(a['result'], list):
                    a['result'] = [a['result']]
        client.import_tasks(id=project_id, tasks=tasks)
    else:
        raise

Prevention

When it happens

Trigger: POSTing tasks with {'annotations': [{'result': {'id': 1, ...}}]} (object instead of array) or {'result': 'some string'}; also {'result': null} since isinstance(None, list) is False.

Common situations: Export converters that serialize a single result object instead of wrapping it in an array; JSON template mistakes where 'result' was set to a dict of results keyed by field; clients porting from other labeling formats where results are maps.

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


AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29). Data as JSON: /api/errors/5b376954e4d06d09. Report an issue: GitHub.