{"record":{"id":"5b376954e4d06d09","repo":"HumanSignal/label-studio","slug":"result-field-in-annotation-must-be-list","errorCode":null,"errorMessage":"\"result\" field in annotation must be list","messagePattern":"\"result\" field in annotation must be list","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"label_studio/tasks/validation.py","lineNumber":180,"sourceCode":"            # task[data]\n            self.raise_if_wrong_class(task, 'data', (dict, list))\n            self.check_data_and_root(self.project, task['data'])\n\n            # task[annotations]: we can't use AnnotationSerializer for validation\n            # because it's much different with validation we need here\n            self.raise_if_wrong_class(task, 'annotations', list)\n            for annotation in task.get('annotations', []):\n                if not isinstance(annotation, dict):\n                    logger.warning('Annotation must be dict, but \"%s\" found', str(type(annotation)))\n                    continue\n\n                ok = 'result' in annotation\n                if not ok:\n                    raise ValidationError('Annotation must have \"result\" fields')\n\n                # check result is list\n                if not isinstance(annotation.get('result', []), list):\n                    raise ValidationError('\"result\" field in annotation must be list')\n\n            # task[predictions]\n            self.raise_if_wrong_class(task, 'predictions', list)\n            for prediction in task.get('predictions', []):\n                if not isinstance(prediction, dict):\n                    logger.warning('Prediction must be dict, but \"%s\" found', str(type(prediction)))\n                    continue\n\n                ok = 'result' in prediction\n                if not ok:\n                    raise ValidationError('Prediction must have \"result\" fields')\n\n            # task[meta]\n            self.raise_if_wrong_class(task, 'meta', (dict, list))\n\n        # task is data as is, validate task as data and move it to task['data']\n        else:\n            self.check_data_and_root(self.project, task, dict_is_root=True)","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/tasks/validation.py#L162-L198","documentation":"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.","triggerScenarios":"POSTing tasks with {'annotations': [{'result': {'id': 1, ...}}]} (object instead of array) or {'result': 'some string'}; also {'result': null} since isinstance(None, list) is False.","commonSituations":"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.","solutions":["Wrap the result value in a list: 'result': [result_obj]","If result is a dict of multiple results, convert to a list of individual result objects","Check the incoming JSON for result: null and replace with an empty list or drop the annotation","Pre-validate with isinstance(a['result'], list) before POSTing"],"exampleFix":"// before\n{\"annotations\": [{\"result\": {\"type\": \"labels\", \"value\": {\"labels\": [\"A\"]}}}]}\n// after\n{\"annotations\": [{\"result\": [{\"type\": \"labels\", \"value\": {\"labels\": [\"A\"]}}]}]}","handlingStrategy":"type-guard","validationCode":"for task in tasks:\n    for a in task.get('annotations', []):\n        if isinstance(a, dict) and 'result' in a and not isinstance(a['result'], list):\n            a['result'] = [a['result']] if a['result'] is not None else []","typeGuard":"def is_annotation(a):\n    return isinstance(a, dict) and isinstance(a.get('result'), list)","tryCatchPattern":"try:\n    client.import_tasks(id=project_id, tasks=tasks)\nexcept LabelStudioError as e:\n    if 'result\" field in annotation must be list' in str(e):\n        for t in tasks:\n            for a in t.get('annotations', []):\n                if 'result' in a and not isinstance(a['result'], list):\n                    a['result'] = [a['result']]\n        client.import_tasks(id=project_id, tasks=tasks)\n    else:\n        raise","preventionTips":["Wrap single result objects in a list before import","Convert result maps/dicts into arrays of result objects","Never emit result: null — use [] or omit the annotation","Unit-test your export converter output against the Label Studio task schema"],"tags":["validation","task-import","annotations","type-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}