langgenius/dify · error · NotFound

UploadFile not found.

Error message

UploadFile not found.

What it means

Raised by the segment batch-import POST endpoint when the supplied upload_file_id does not resolve to a row in the UploadFile table. The controller verifies dataset and document first, then loads the UploadFile by id; a None result triggers flask-restx NotFound (HTTP 404). It means the file referenced by the request body was never uploaded, was deleted, or does not belong to the tenant scope the query sees.

Source

Thrown at api/controllers/console/datasets/datasets_segments.py:647

        dataset_id: UUID,
        document_id: UUID,
    ):
        # check dataset
        dataset_id_str = str(dataset_id)
        dataset = DatasetService.get_dataset(dataset_id_str, session)
        if not dataset:
            raise NotFound("Dataset not found.")
        # check document
        document_id_str = str(document_id)
        document = DocumentService.get_document(dataset_id_str, document_id_str, session=session)
        if not document:
            raise NotFound("Document not found.")

        upload_file_id = req_data.upload_file_id

        upload_file = session.scalar(select(UploadFile).where(UploadFile.id == upload_file_id).limit(1))
        if not upload_file:
            raise NotFound("UploadFile not found.")

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

        try:
            # async job
            job_id = str(uuid.uuid4())
            indexing_cache_key = f"segment_batch_import_{job_id}"
            # send batch add segments task
            redis_client.setnx(indexing_cache_key, "waiting")
            batch_create_segment_to_index_task.delay(
                job_id,
                upload_file_id,
                dataset_id_str,
                document_id_str,
                current_tenant_id,
                current_user.id,

View on GitHub (pinned to ef8544b173)

Solutions

  1. Re-run the file upload and capture the returned upload_file_id, then re-send the batch_import request with that fresh id.
  2. Confirm the upload_file_id belongs to the same tenant by checking the upload history endpoint before submitting the import.
  3. If the file was intentionally deleted, upload a new CSV and use its id.

Example fix

// before
POST .../segments/batch_import  body: {"upload_file_id": "<stale id>"}
// after
1) POST .../files/upload  (multipart: the .csv)  ->  {"id": "<new_id>"}
2) POST .../segments/batch_import  body: {"upload_file_id": "<new_id>"}
Defensive patterns

Strategy: validation

Validate before calling

// Before POSTing batch_import, verify the upload file id resolves to a CSV.
async function safeBatchImport(uploadFileId, ids) {
  const fileMeta = await fetch(`/console/api/files/upload/${uploadFileId}`).then(r => r.ok ? r.json() : null);
  if (!fileMeta) throw new Error('upload_file_id is invalid; re-upload the CSV first');
  return fetch(`/console/api/datasets/${ids.dataset}/documents/${ids.document}/segments/batch_import`, {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({upload_file_id: uploadFileId}),
  });
}

Type guard

function isValidUploadFileId(id) {
  return typeof id === 'string' && /^[0-9a-fA-F-]{36}$/.test(id) && id !== '00000000-0000-0000-0000-000000000000';
}

Try / catch

try {
  await batchImport(uploadFileId, ids);
} catch (e) {
  if (e.status === 404 && /UploadFile not found/.test(e.message)) {
    // re-upload then retry once with the new id
    const fresh = await uploadCsv(file);
    await batchImport(fresh.id, ids);
  } else throw e;
}

Prevention

When it happens

Trigger: POST /console/api/datasets/{dataset_id}/documents/{document_id}/segments/batch_import with a Body.upload_file_id that does not exist in the UploadFile table. Common when the upload step returns an id but it has since been removed, when an id from a different workspace is reused, or when the frontend sends the field as null/empty after a failed upload.

Common situations: Uploading a CSV through the file-upload endpoint, then waiting long enough that the file is cleaned up before the import POST fires; copy-pasting an upload_file_id from another tenant; the upload step silently failed and returned no id while the UI still submits.

Related errors


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