HumanSignal/label-studio · error · ValidationError

All tasks are empty (None)

Error message

All tasks are empty (None)

What it means

TaskValidator.to_internal_value raises this when the whole payload passed to task import is None. Since there is nothing to iterate over, the validator fails fast with this message instead of the more specific per-item errors.

Source

Thrown at label_studio/tasks/validation.py:216

            self.check_data_and_root(self.project, task, dict_is_root=True)
            task = {'data': task}

        return task

    @staticmethod
    def format_error(i, detail, item):
        if len(detail) == 1:
            code = (str(detail[0].code + ' ')) if detail[0].code != 'invalid' else ''
            return 'Error {code} at item {i}: {detail} :: {item}'.format(code=code, i=i, detail=detail[0], item=item)
        else:
            errors = ', '.join(detail)
            codes = str([d.code for d in detail])
            return 'Errors {codes} at item {i}: {errors} :: {item}'.format(codes=codes, i=i, errors=errors, item=item)

    def to_internal_value(self, data):
        """Body of run_validation for all data items"""
        if data is None:
            raise ValidationError('All tasks are empty (None)')

        if not isinstance(data, list):
            raise ValidationError('data is not a list')

        if len(data) == 0:
            raise ValidationError('data is empty')

        ret, errors = [], []
        self.annotation_count, self.prediction_count = 0, 0
        for i, item in enumerate(data):
            try:
                validated = self.validate(item)
            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] = '...'

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Send a JSON array of task objects as the request body, e.g. [{"data": {...}}]
  2. Check the upstream variable producing the payload and fix why it is None
  3. Ensure Content-Type is application/json and the body is actually transmitted
  4. Guard in client code: if not tasks: raise ValueError('no tasks to import') before calling the API

Example fix

// before
requests.post(url, headers=headers)  # no body -> data is None
// after
requests.post(url, json=[{"data": {"text": "hi"}}], headers=headers)
Defensive patterns

Strategy: validation

Validate before calling

if tasks is None:
    raise ValueError('tasks payload is None; provide a non-empty JSON array of task objects')

Type guard

def is_valid_payload(tasks):
    return isinstance(tasks, list) and len(tasks) > 0

Try / catch

try:
    client.import_tasks(id=project_id, tasks=tasks)
except LabelStudioError as e:
    if 'All tasks are empty (None)' in str(e):
        raise ValueError('No task payload was sent; check the variable feeding the import call') from e
    raise

Prevention

When it happens

Trigger: POSTing an import request with an empty body (no JSON), or with explicit JSON null as the body; calling run_validation(None) directly; an HTTP client sending a request whose parsed body yields None (e.g. wrong Content-Type with empty data).

Common situations: API clients forgetting to attach a body; scripts reading task data from a file that turns out empty and passing the parsed None; SDK calls where the tasks argument was omitted or a variable referencing an unloaded value is None.

Related errors


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