langgenius/dify · error · ValueError

The uploaded file is empty

Error message

The uploaded file is empty

What it means

Raised by AnnotationBatchImportApi.post after the size check, when file_size == 0 bytes. Like the file-type check this is a raw ValueError, surfaced as a 400 through Flask's default handler rather than Dify's structured envelope. It catches CSVs that passed the extension check but contain no data.

Solutions

  1. Open the CSV locally and confirm it contains at least a header row and data.
  2. If using a script to generate the file, raise an error in the script when zero rows are produced so you never send an empty file.
  3. Re-run the export and verify the file size on disk is > 0 before uploading.
  4. Check the upload client for truncation (e.g., incorrect binary mode in transfer).

Example fix

# before
with open('annotations.csv', 'w') as f:  # accidentally creates empty file
    pass

# after
import os
assert os.path.getsize('annotations.csv') > 0, 'CSV is empty; regenerate it'
Defensive patterns

Strategy: validation

Validate before calling

function assertNonEmptyFile(file) {
  if (file.size === 0) throw new Error('CSV file is empty');
  return file;
}

Type guard

const isNonEmptyFile = (file) => !!file && file.size > 0;

Try / catch

try { await fetch(url, { method: 'POST', body: form }); }
catch (e) { if (/empty/.test(e.message)) alert('The selected CSV has no content.'); }

Prevention

When it happens

Trigger: Uploading a newly-created empty CSV file (just headers absent); a truncated upload where the connection dropped mid-transfer leaving a zero-byte temp file; a template file that was never populated; a symbolic link pointing to /dev/null.

Common situations: Automated export pipeline writes the file but the source query returns zero rows and the writer leaves the file empty; CI test fixture checked in as an empty file; FTP/SFTP transfer mode stripping all content.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/1cf626bc936a7050. Report an issue: GitHub.

Appendix: source

Thrown at api/controllers/console/app/annotation.py:494

        # check file type
        if not file.filename or not file.filename.lower().endswith(".csv"):
            raise ValueError("Invalid file type. Only CSV files are allowed")

        # Check file size before processing
        file.stream.seek(0, 2)  # Seek to end of file
        file_size = file.stream.tell()
        file.stream.seek(0)  # Reset to beginning

        max_size_bytes = dify_config.ANNOTATION_IMPORT_FILE_SIZE_LIMIT * 1024 * 1024
        if file_size > max_size_bytes:
            abort(
                413,
                f"File size exceeds maximum limit of {dify_config.ANNOTATION_IMPORT_FILE_SIZE_LIMIT}MB. "
                f"Please reduce the file size and try again.",
            )

        if file_size == 0:
            raise ValueError("The uploaded file is empty")

        return dump_response(
            AnnotationBatchImportResponse,
            AppAnnotationService.batch_import_app_annotations(str(app_id), file, session),
        )


@console_ns.route("/apps/<uuid:app_id>/annotations/batch-import-status/<uuid:job_id>")
class AnnotationBatchImportStatusApi(Resource):
    @console_ns.doc("get_batch_import_status")
    @console_ns.doc(description="Get status of batch import job")
    @console_ns.doc(params={"app_id": "Application ID", "job_id": "Job ID"})
    @console_ns.response(
        200, "Job status retrieved successfully", console_ns.models[AnnotationJobStatusDetailResponse.__name__]
    )
    @console_ns.response(403, "Insufficient permissions")
    @setup_required
    @login_required

View on GitHub (pinned to ef8544b173)