HumanSignal/label-studio · error · ValidationError

"url" must be 2048 characters or fewer

Error message

"url" must be 2048 characters or fewer

What it means

Label Studio limits the 'url' form field on urlencoded sync imports to 2048 characters. If a longer string is supplied, load_tasks raises this ValidationError before attempting to fetch or parse it, protecting against abuse of the url field as an inline data channel.

Source

Thrown at label_studio/data_import/uploader.py:365

    # take tasks from request FILES
    if len(request.FILES) > 0:
        check_request_files_size(request.FILES)
        check_extensions(request.FILES)
        for filename, file in request.FILES.items():
            file_upload = create_file_upload(request.user, project, file)
            if file_upload.format_could_be_tasks_list:
                could_be_tasks_list = True
            file_upload_ids.append(file_upload.id)
        tasks, found_formats, data_keys = FileUpload.load_tasks_from_uploaded_files(project, file_upload_ids)

    # take tasks from url address
    elif 'application/x-www-form-urlencoded' in request.content_type:
        # empty url
        url = request.data.get('url')
        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')

        # try to load json with task or tasks from url as string
        json_data = str_to_json(url)
        if json_data:
            file_upload = create_file_upload(request.user, project, SimpleUploadedFile('inplace.json', url.encode()))
            file_upload_ids.append(file_upload.id)
            tasks, found_formats, data_keys = FileUpload.load_tasks_from_uploaded_files(project, file_upload_ids)

        # download file using url and read tasks from it
        else:
            (
                data_keys,
                found_formats,
                tasks,
                file_upload_ids,
                could_be_tasks_list,
            ) = tasks_from_url(file_upload_ids, project, request.user, url, could_be_tasks_list)

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Host the task data at a real URL and pass that (short) URL instead of inlining the data
  2. Use the file-upload or JSON-body import path for large payloads
  3. Shorten the URL (remove query params, use a URL shortener) if it is genuinely a URL

Example fix

// before
requests.post(url, data={"url": "[{" + huge_tasks_json + "}]"})
// after
requests.post(url, json=huge_tasks_list)  # or upload via files=
Defensive patterns

Strategy: validation

Validate before calling

if url and len(url) > 2048:
    raise ValueError('url exceeds the 2048 character limit; host data at a real URL instead')

Type guard

def is_valid_import_url(url):
    return isinstance(url, str) and 0 < len(url) <= 2048 and url.startswith(('http://', 'https://'))

Try / catch

try:
    import_via_url(url)
except ValidationError as e:
    if '2048 characters' in str(e):
        import_via_file_upload(upload_bytes(url.encode()))  # fallback path
    else:
        raise

Prevention

When it happens

Trigger: POSTing application/x-www-form-urlencoded data with a 'url' field longer than 2048 chars — typically someone pasting large JSON task data directly into the url field instead of giving a real URL.

Common situations: Inlining JSON payloads in url=... (they parse via str_to_json but oversize ones are rejected); URLs with very long query strings or embedded tokens; generated pre-signed URLs exceeding the limit.

Related errors


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