HumanSignal/label-studio · error · ValueError
"file_upload_ids" parameter must be a list of integers
Error message
"file_upload_ids" parameter must be a list of integers
What it means
The FileUpload delete endpoint accepts 'file_upload_ids' in the request body: None deletes ALL uploads for the project, a list deletes only those IDs, and any other type raises this plain ValueError. It is a Python ValueError, not DRF ValidationError, so it typically surfaces as a 500 rather than a structured 400.
Source
Thrown at label_studio/data_import/api.py:863
return FileUpload.objects.filter(project_id=project.id, user=self.request.user)
# If requested in regular import, only queried IDs are returned to avoid showing previously imported
ids = json.loads(self.request.query_params.get('ids', '[]'))
logger.debug(f'File Upload IDs found: {ids}')
return FileUpload.objects.filter(project_id=project.id, id__in=ids, user=self.request.user)
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
project = generics.get_object_or_404(Project.objects.for_user(self.request.user), pk=self.kwargs['pk'])
ids = self.request.data.get('file_upload_ids')
if ids is None:
deleted, _ = FileUpload.objects.filter(project=project).delete()
elif isinstance(ids, list):
deleted, _ = FileUpload.objects.filter(project=project, id__in=ids).delete()
else:
raise ValueError('"file_upload_ids" parameter must be a list of integers')
return Response({'deleted': deleted}, status=status.HTTP_200_OK)
@method_decorator(
name='get',
decorator=extend_schema(
tags=['Import'],
summary='Get file upload',
description='Retrieve details about a specific uploaded file.',
extensions={
'x-fern-sdk-group-name': ['files'],
'x-fern-sdk-method-name': 'get',
'x-fern-audiences': ['public'],
},
),
)
@method_decorator(
name='patch',View on GitHub (pinned to 0b49e9b539)
Solutions
- Send file_upload_ids as a JSON array of integers: {"file_upload_ids": [1, 2, 3]}
- If deleting a single upload, still wrap it: [42], not 42
- If you intended to delete everything, explicitly pass null / omit the key — review carefully, this deletes ALL project uploads
- Handle the string case: convert a comma-separated string to a list of ints before sending
- Report/handle the 500-style ValueError response in client error handling since it is not a structured 400
Example fix
// before
requests.post(url, headers=headers, json={"file_upload_ids": 42})
// after
requests.post(url, headers=headers, json={"file_upload_ids": [42]}) Defensive patterns
Strategy: type-guard
Validate before calling
ids = body.get('file_upload_ids')
if ids is not None and not (isinstance(ids, list) and all(isinstance(i, int) for i in ids)):
raise ValueError('file_upload_ids must be a list of integers (or null to delete all)') Type guard
def is_valid_upload_ids(v) -> bool:
return v is None or (isinstance(v, list) and all(isinstance(i, int) and not isinstance(i, bool) for i in v)) Try / catch
try:
resp = requests.post(delete_url, headers=H, json={'file_upload_ids': ids})
resp.raise_for_status()
except requests.HTTPError as e:
if 'must be a list of integers' in e.response.text:
raise TypeError('Wrap the id in a list: {"file_upload_ids": [42]}') Prevention
- Always wrap single IDs in a list before sending
- Confirm json= (not data=) is used so lists survive serialization
- Be deliberate about null/omitted file_upload_ids: it deletes ALL project uploads
- Reject bools and numeric strings client-side before sending
When it happens
Trigger: POST/DELETE to the file-upload delete endpoint (api.FileUploadListDelete) with body {'file_upload_ids': <non-list>} — e.g. a single integer 5, a string "5", a dict, or a comma-separated string — instead of a JSON array of integers.
Common situations: Client sending a single ID without wrapping it in a list; form-encoded bodies where lists get serialized as strings; scripts passing a tuple or a set; frontend JSON.stringify mistakes; dangerously sending null/omitting the key and wiping all uploads instead (the None branch is total deletion).
Related errors
- Prediction validation failed ({len(validation_errors)} error
- "url" is not found in request data
- "url" must be 2048 characters or fewer
- load_tasks: No data found in DATA or in FILES
- {item} contains invalid "task" field: task ID {task_id} not
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/3255a9a17177d436.
Report an issue: GitHub.