HumanSignal/label-studio · error · ValidationError

load_tasks: No data found in DATA or in FILES

Error message

load_tasks: No data found in DATA or in FILES

What it means

async_import dispatches on request content type: file upload (multipart), urlencoded url import, or JSON body with tasks. If none of these branches matched — no FILES, not urlencoded, and body not a JSON list/dict of tasks — it falls into the 'incorrect data source' else branch and raises this ValidationError. It is the 'we received nothing importable' error.

Source

Thrown at label_studio/data_import/api.py:409

            if not url:
                raise ValidationError('"url" is not found in request data')
            if len(url) > 2048:
                raise ValidationError('"url" must be 2048 characters or fewer')
            project_import.url = url
            project_import.save(update_fields=['url'])
        # take one task from request DATA
        elif 'application/json' in request.content_type and isinstance(request.data, dict):
            project_import.tasks = [request.data]
            project_import.save(update_fields=['tasks'])

        # take many tasks from request DATA
        elif 'application/json' in request.content_type and isinstance(request.data, list):
            project_import.tasks = request.data
            project_import.save(update_fields=['tasks'])

        # incorrect data source
        else:
            raise ValidationError('load_tasks: No data found in DATA or in FILES')

        start_job_async_or_sync(
            async_import_background,
            project_import.id,
            request.user.id,
            queue_name='high',
            on_failure=set_import_background_failure,
            project_id=project.id,
            organization_id=request.user.active_organization.id,
        )

        response = {'import': project_import.id}
        return Response(response, status=status.HTTP_201_CREATED)

    def create(self, request, *args, **kwargs):
        commit_to_project = bool_from_request(request.query_params, 'commit_to_project', True)
        return_task_ids = bool_from_request(request.query_params, 'return_task_ids', False)
        preannotated_from_fields = list_of_strings_from_request(request.query_params, 'preannotated_from_fields', None)

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Send tasks as a JSON array: requests.post(url, json=[{...task...}]) so Content-Type and body match
  2. If importing a file, send it as multipart/form-data with the file part (requests files= parameter)
  3. If importing from a URL, use application/x-www-form-urlencoded with a non-empty 'url' field
  4. Log/inspect the exact request body and Content-Type actually sent (curl -v) to see which branch failed
  5. Ensure upstream data generation is not producing an empty payload

Example fix

# before: string body treated as neither list nor dict
requests.post(url, headers={'Content-Type': 'application/json'}, data='{"data": {}}')
# after: proper JSON list of tasks
requests.post(url, json=[{"data": {"text": "hello"}}])
Defensive patterns

Strategy: validation

Validate before calling

assert tasks and isinstance(tasks, list), 'payload must be a non-empty JSON list of tasks'
assert all(isinstance(t, dict) and 'data' in t for t in tasks), 'each task must be an object with a data key'

Type guard

def is_valid_import_payload(body) -> bool:
    return isinstance(body, list) and len(body) > 0 and all(isinstance(i, dict) for i in body)

Try / catch

try:
    resp = requests.post(import_url, headers=H, json=tasks)
    resp.raise_for_status()
except requests.HTTPError as e:
    if 'No data found in DATA or in FILES' in e.response.text:
        log.error('Body/Content-Type mismatch: sent %r %r', req_content_type, req_body_preview)

Prevention

When it happens

Trigger: POST /api/projects/{id}/import with an empty body; Content-Type application/json but body is an empty string, an empty dict with no recognizable task data handled by earlier branches, or a non-dict/non-list scalar (e.g. plain text body); missing multipart file field with no other data.

Common situations: Client sends JSON with Content-Type: application/json but body serialized as a string of text rather than a JSON array/object; upload script posts a form without the file part; gateway/proxy strips the request body; automation passing an empty list after an upstream job produced no tasks; sending text/csv body with an unsupported content type.

Related errors


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