{"record":{"id":"9e39774654cd5b7e","repo":"HumanSignal/label-studio","slug":"no-converted-file-found-probably-there-are-no-ann","errorCode":null,"errorMessage":"No converted file found, probably there are no annotations in the export snapshot","messagePattern":"No converted file found, probably there are no annotations in the export snapshot","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"warning","filePath":"label_studio/data_export/api.py","lineNumber":622,"sourceCode":"\n\ndef async_convert(converted_format_id, export_type, project, hostname, download_resources=False, **kwargs):\n    with transaction.atomic():\n        try:\n            converted_format = ConvertedFormat.objects.get(id=converted_format_id)\n        except ConvertedFormat.DoesNotExist:\n            logger.error(f'ConvertedFormat with id {converted_format_id} not found, conversion failed')\n            return\n        if converted_format.status != ConvertedFormat.Status.CREATED:\n            logger.error(f'Conversion for export id {converted_format.export.id} to {export_type} already started')\n            return\n        converted_format.status = ConvertedFormat.Status.IN_PROGRESS\n        converted_format.save(update_fields=['status'])\n\n    snapshot = converted_format.export\n    converted_file = snapshot.convert_file(export_type, download_resources=download_resources, hostname=hostname)\n    if converted_file is None:\n        raise ValidationError('No converted file found, probably there are no annotations in the export snapshot')\n    md5 = Export.eval_md5(converted_file)\n    ext = converted_file.name.split('.')[-1]\n\n    now = datetime.now()\n    file_name = f'project-{project.id}-at-{now.strftime(\"%Y-%m-%d-%H-%M\")}-{md5[0:8]}.{ext}'\n    file_path = f'{project.id}/{file_name}'  # finally file will be in settings.DELAYED_EXPORT_DIR/project.id/file_name\n    file_ = File(converted_file, name=file_path)\n    converted_format.file.save(file_path, file_)\n    converted_format.status = ConvertedFormat.Status.COMPLETED\n    converted_format.save(update_fields=['file', 'status'])\n\n\ndef set_convert_background_failure(job, connection, type, value, traceback_obj):\n    from data_export.models import ConvertedFormat\n\n    convert_id = job.args[0]\n    try:\n        trace = ''.join(tb.format_exception(type, value, traceback_obj))","sourceCodeStart":604,"sourceCodeEnd":640,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/data_export/api.py#L604-L640","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the project/snapshot has completed annotations before exporting; re-create the snapshot including annotated tasks.","Check the snapshot's task filter/query and re-export without filters that exclude all annotations.","Trigger the export/download as JSON, which tolerates empty results.","If annotations exist but are drafts, submit them so they count as completed in the export."],"exampleFix":"# before: convert on empty snapshot -> ValidationError\nPOST /api/projects/1/exports/empty-snapshot/convert\n\n# after: re-export snapshot with annotated tasks, then convert\nPOST /api/projects/1/exports  (download_resources=..., query includes annotated tasks)\nPOST /api/projects/1/exports/<new-snapshot>/convert","handlingStrategy":"validation","validationCode":"def convertible(snapshot):\n    return snapshot.tasks.exists() and any(t.annotations.exists() for t in snapshot.tasks.all())","typeGuard":null,"tryCatchPattern":"try:\n    trigger_conversion(snapshot_id, 'XLSX')\nexcept ValidationError as e:\n    if 'No converted file found' in str(e):\n        logging.info('Snapshot %s has no annotations; skipping conversion', snapshot_id)\n    else:\n        raise","preventionTips":["Verify the snapshot's query actually includes annotated tasks before exporting","Submit draft annotations so they count as completed","Fall back to JSON export when datasets are empty"],"tags":["data-export","empty-dataset","async-job","validation"],"backgroundTag":"export-format-not-ready","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}