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.
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_requiredView on GitHub (pinned to ef8544b173)
Solutions
- Open the CSV locally and confirm it contains at least a header row and data.
- 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.
- Re-run the export and verify the file size on disk is > 0 before uploading.
- 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
- Check file.size > 0 in the UI before submit.
- Validate export pipelines never emit zero-byte files.
- Log file size at upload time for debugging.
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
- Invalid file type. Only CSV files are allowed
- no_file_uploaded
- too_many_files
- no_audio_uploaded
- unsupported_audio_type
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/1cf626bc936a7050.
Report an issue: GitHub.