HumanSignal/label-studio · error · ValidationError
Annotation must have "result" fields
Error message
Annotation must have "result" fields
What it means
TaskValidator.validate in label_studio/tasks/validation.py raises this DRF ValidationError when a task item's 'annotations' list contains a dict entry that has no 'result' key. Label Studio's task import format requires every annotation to carry a 'result' array holding the labeling results, so an annotation without it is considered malformed and the whole import batch is rejected.
Source
Thrown at label_studio/tasks/validation.py:176
raise ValidationError('Task root must be dict with "data", "meta", "annotations", "predictions" fields')
# task[data] | task[annotations] | task[predictions] | task[meta]
if self.check_allowed(task):
# 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))View on GitHub (pinned to 0b49e9b539)
Solutions
- Add a 'result' key with a list value to every annotation dict, e.g. 'result': [] for a no-op annotation
- If the annotation has no labeling results, import it without the 'annotations' key entirely
- Validate the import JSON locally before POSTing: for each task, for each a in task.get('annotations', []): assert isinstance(a.get('result'), list)
- Remove pre-annotations/annotations from the payload if you only intend to import raw task data
Example fix
// before
{"data": {"text": "hi"}, "annotations": [{"completed_by": 1}]}
// after
{"data": {"text": "hi"}, "annotations": [{"completed_by": 1, "result": []}]} Defensive patterns
Strategy: validation
Validate before calling
def validate_annotations(task):
for a in task.get('annotations', []):
if isinstance(a, dict) and 'result' not in a:
raise ValueError('annotation missing result: %r' % a)
if isinstance(a, dict) and not isinstance(a['result'], list):
raise ValueError('annotation result must be a list') Type guard
def has_valid_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 'Annotation must have "result" fields' in str(e):
tasks = [fix_annotation(t) for t in tasks]
client.import_tasks(id=project_id, tasks=tasks)
else:
raise Prevention
- Always include 'result': [] in annotation dicts, even when empty
- Never copy annotation metadata from foreign tools without adding a result array
- Run a local schema check on annotations before import
- Drop the 'annotations' key entirely if you have no annotation results
When it happens
Trigger: POSTing tasks to the task import API (e.g. /api/projects/<id>/import) with an item like {'data': {...}, 'annotations': [{'completed_by': 1}]} — an annotation dict present but missing 'result'. Only annotation entries that are dicts trigger this; non-dict entries are skipped with a warning.
Common situations: Scripts exporting annotations from other tools (or older Label Studio exports) that omit 'result'; hand-written import JSON where only annotations metadata (lead_time, completed_by) was copied; API clients building annotations programmatically and forgetting the results array.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- "result" field in annotation must be list
- Prediction must have "result" fields
- All tasks are empty (None)
- data is not a list
- data is empty
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/79937e2a597f1a8d.
Report an issue: GitHub.