HumanSignal/label-studio · error · ValidationError

Can't deserialize tasks due to {errors}

Error message

Can't deserialize tasks due to {errors}

What it means

Raised in BaseTaskSerializerBulk.to_internal_value when one or more task items in an import batch fail per-item validation (self.child.validate / ValidationError). Each failed item is formatted as 'Error... at item i: ...' and the collected list is raised as a single DRF ValidationError after the loop, so the whole import batch is rejected. The library throws it to surface per-task deserialization problems with the offending item echoed for debugging.

Source

Thrown at label_studio/tasks/serializers.py:558

            except ValidationError as exc:
                error = self.format_error(i, exc.detail, item)
                errors.append(error)
                # do not print to user too many errors
                if len(errors) >= 100:
                    errors[99] = '...'
                    break
            else:
                ret.append(validated)
                errors.append({})

                if 'annotations' in item:
                    self.annotation_count += len(item['annotations'])
                if 'predictions' in item:
                    self.prediction_count += len(item['predictions'])

        if any(errors):
            logger.warning("Can't deserialize tasks due to " + str(errors))
            raise ValidationError(errors)

        return ret

    @staticmethod
    def _insert_valid_completed_by(annotations, members_email_to_id, members_ids, default_user, ff_user=None):
        """Insert the correct id for completed_by by email/id in annotations.

        Two modes of operation, gated on
        ``fflag_fix_back_bros_1092_import_unknown_completed_by_short``:

        - FF on (BROS-1092 default): unknown annotators are silently re-attributed
          to ``default_user`` via :func:`resolve_completed_by_id` so cross-org
          re-imports do not 400. ``default_user`` here is the importer (when
          available in serializer context) or ``project.created_by`` as set by
          :meth:`BaseTaskSerializerBulk.create`.
        - FF off: keeps the historical strict validation that raises
          ``ValidationError`` for any value that doesn't resolve to an org member,
          preserving the legacy behavior for rollback.

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Read the 'at item i' messages in the error detail to find the offending tasks and fix the data (the item is echoed inline)
  2. Ensure every task object contains the fields required by the project's labeling config (e.g. a 'data' dict with the configured data key like 'image' or 'text')
  3. Re-export from the source project with the same label config, or update Label Studio so the export format matches the importer
  4. Split the batch and import items individually to isolate the bad records; fix or drop them
  5. Enable logging at WARNING+ to see the full 'Can't deserialize tasks due to [...]' list which may be capped at 100 entries in the response

Example fix

// before
payload = [{"data": {}}, {"data": {"text": "ok"}}]
client.import_tasks(project_id, payload)  # first item fails: missing configured data key
// after
payload = [{"data": {"text": "hello"}}, {"data": {"text": "ok"}}]
client.import_tasks(project_id, payload)
Defensive patterns

Strategy: validation

Validate before calling

def validate_import_batch(tasks, required_data_key):
    errors = []
    for i, t in enumerate(tasks):
        if not isinstance(t, dict):
            errors.append(f'item {i}: not an object')
            continue
        data = t.get('data')
        if not isinstance(data, dict) or required_data_key not in data:
            errors.append(f'item {i}: data missing key {required_data_key!r}: {t}')
    if errors:
        raise ValueError('Invalid task items: ' + '; '.join(errors[:5]))

Type guard

def is_valid_task_item(t, required_data_key):
    return isinstance(t, dict) and isinstance(t.get('data'), dict) and required_data_key in t['data']

Try / catch

from rest_framework.exceptions import ValidationError
try:
    client.import_tasks(project_id, tasks)
except ValidationError as e:
    for msg in (e.detail if isinstance(e.detail, list) else [e.detail]):
        print('Item error:', msg)  # each contains 'at item i:' with the offending payload
    # fix or drop the flagged items and retry

Prevention

When it happens

Trigger: POSTing a task import batch (task bulk create API / SDK importer) where at least one item in the JSON list fails the TaskSerializer.validate — e.g. a task missing required data keys, invalid label values, wrong types, or annotations/predictions in an invalid shape.

Common situations: Importing a Label Studio export snapshot from a different project/label config; hand-edited JSON with a malformed task; uploading CSV/JSON where one row has null or wrong-typed fields; version drift where a newer export format contains fields the current serializer rejects.

Related errors


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