HumanSignal/label-studio · warning · ValidationError

No converted file found, probably there are no annotations i

Error message

No converted file found, probably there are no annotations in the export snapshot

What it means

async_convert runs the snapshot's convert_file to produce a file in the requested format; if convert_file returns None — which happens when there is nothing to convert, e.g. the export snapshot contains no annotations — the task raises ValidationError with this message and the ConvertedFormat is marked failed.

Source

Thrown at label_studio/data_export/api.py:622


def async_convert(converted_format_id, export_type, project, hostname, download_resources=False, **kwargs):
    with transaction.atomic():
        try:
            converted_format = ConvertedFormat.objects.get(id=converted_format_id)
        except ConvertedFormat.DoesNotExist:
            logger.error(f'ConvertedFormat with id {converted_format_id} not found, conversion failed')
            return
        if converted_format.status != ConvertedFormat.Status.CREATED:
            logger.error(f'Conversion for export id {converted_format.export.id} to {export_type} already started')
            return
        converted_format.status = ConvertedFormat.Status.IN_PROGRESS
        converted_format.save(update_fields=['status'])

    snapshot = converted_format.export
    converted_file = snapshot.convert_file(export_type, download_resources=download_resources, hostname=hostname)
    if converted_file is None:
        raise ValidationError('No converted file found, probably there are no annotations in the export snapshot')
    md5 = Export.eval_md5(converted_file)
    ext = converted_file.name.split('.')[-1]

    now = datetime.now()
    file_name = f'project-{project.id}-at-{now.strftime("%Y-%m-%d-%H-%M")}-{md5[0:8]}.{ext}'
    file_path = f'{project.id}/{file_name}'  # finally file will be in settings.DELAYED_EXPORT_DIR/project.id/file_name
    file_ = File(converted_file, name=file_path)
    converted_format.file.save(file_path, file_)
    converted_format.status = ConvertedFormat.Status.COMPLETED
    converted_format.save(update_fields=['file', 'status'])


def set_convert_background_failure(job, connection, type, value, traceback_obj):
    from data_export.models import ConvertedFormat

    convert_id = job.args[0]
    try:
        trace = ''.join(tb.format_exception(type, value, traceback_obj))

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Ensure the project/snapshot has completed annotations before exporting; re-create the snapshot including annotated tasks.
  2. Check the snapshot's task filter/query and re-export without filters that exclude all annotations.
  3. Trigger the export/download as JSON, which tolerates empty results.
  4. If annotations exist but are drafts, submit them so they count as completed in the export.

Example fix

# before: convert on empty snapshot -> ValidationError
POST /api/projects/1/exports/empty-snapshot/convert

# after: re-export snapshot with annotated tasks, then convert
POST /api/projects/1/exports  (download_resources=..., query includes annotated tasks)
POST /api/projects/1/exports/<new-snapshot>/convert
Defensive patterns

Strategy: validation

Validate before calling

def convertible(snapshot):
    return snapshot.tasks.exists() and any(t.annotations.exists() for t in snapshot.tasks.all())

Try / catch

try:
    trigger_conversion(snapshot_id, 'XLSX')
except ValidationError as e:
    if 'No converted file found' in str(e):
        logging.info('Snapshot %s has no annotations; skipping conversion', snapshot_id)
    else:
        raise

Prevention

When it happens

Trigger: Requesting conversion of an export snapshot whose filter selected zero annotated tasks (e.g. exported with 'only annotated' filters), then the async job calls snapshot.convert_file which returns None.

Common situations: Exporting an empty project or a snapshot filtered to tasks without annotations, then trying to convert to CSV/XLSX; completed-but-empty tasks with draft-only annotations excluded from the export.

Related errors


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