HumanSignal/label-studio · error · NotFound

format is not converted yet

Error message

{export_type} format is not converted yet

What it means

When async export conversion is enabled (fflag_fix_all_lsdv_4813...), the export download endpoint get() serves the file converted to the requested export_type. If no ConvertedFormat record with that export_type exists on the export snapshot (conversion never completed), it raises NotFound with this message. Only 'JSON' is available without conversion.

Solutions

  1. First POST to the conversion endpoint for that export_type, wait for completion (status becomes completed), then GET the file.
  2. Poll the ConvertedFormat status via the API before attempting download.
  3. Re-trigger conversion if a prior job failed (FAILED records are retriable via the convert endpoint).
  4. Use export_type=JSON, which is always available from the snapshot without conversion.

Example fix

// before
GET /api/projects/1/exports/abc?export_type=CSV  -> 404 not converted yet

// after
POST /api/projects/1/exports/abc/convert  (export_type=CSV)
# wait until completed
GET /api/projects/1/exports/abc?export_type=CSV
Defensive patterns

Strategy: retry

Validate before calling

def can_download(snapshot, export_type):
    if export_type in (None, 'JSON'):
        return True
    return snapshot.converted_formats.filter(
        export_type=export_type,
        status='completed'
    ).exists()

Try / catch

try:
    file = download_export(snapshot_id, export_type='CSV')
except NotFound:
    trigger_conversion(snapshot_id, 'CSV')
    wait_for_conversion(snapshot_id, 'CSV')  # poll ConvertedFormat status
    file = download_export(snapshot_id, export_type='CSV')

Prevention

When it happens

Trigger: Requesting GET /api/projects/<id>/exports/<snapshot_id>?export_type=CSV (or XLSX etc.) while async conversion is enabled, before the conversion job for that format has produced a ConvertedFormat row.

Common situations: Client polls for a converted format immediately after snapshot creation before the async job finished; a previous conversion failed so no record exists; requesting a format never queued; feature flag recently enabled so legacy snapshots lack converted formats.

Related errors


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

Appendix: source

Thrown at label_studio/data_export/api.py:560

        return project

    def get_queryset(self):
        project = self._get_project()
        return super().get_queryset().filter(project=project)

    def get(self, request, *args, **kwargs):
        snapshot = self.get_object()
        export_type = request.GET.get('exportType')

        if snapshot.status != Export.Status.COMPLETED:
            return HttpResponse('Export is not completed', status=404)

        if flag_set('fflag_fix_all_lsdv_4813_async_export_conversion_22032023_short', request.user):
            file = snapshot.file
            if export_type is not None and export_type != 'JSON':
                converted_file = snapshot.converted_formats.filter(export_type=export_type).first()
                if converted_file is None:
                    raise NotFound(f'{export_type} format is not converted yet')
                file = converted_file.file

            if isinstance(file.storage, FileSystemStorage):
                url = file.storage.url(file.name)
            else:
                url = file.storage.url(file.name, storage_url=True)
            protocol = urlparse(url).scheme
            download_name = snapshot.get_download_filename(file.name)

            # NGINX downloads are a solid way to make uwsgi workers free
            if settings.USE_NGINX_FOR_EXPORT_DOWNLOADS:
                # let NGINX handle it
                response = HttpResponse()
                # below header tells NGINX to catch it and serve, see docker-config/nginx-app.conf
                redirect = '/file_download/' + protocol + '/' + url.replace(protocol + '://', '')
                response['X-Accel-Redirect'] = redirect
                response['Content-Disposition'] = f'attachment; filename="{download_name}"'
                response['filename'] = download_name

View on GitHub (pinned to 0b49e9b539)