HumanSignal/label-studio · error · ValidationError

query parameter "project" is required

Error message

query parameter "project" is required

What it means

The storage list API's get_queryset requires a 'project' query parameter to scope storages to a project. Missing or empty 'project' raises DRF ValidationError with the message 'query parameter "project" is required' (an API-level 400).

Source

Thrown at label_studio/io_storages/api.py:35

from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
from rest_framework.response import Response

logger = logging.getLogger(__name__)


class ImportStorageListAPI(generics.ListCreateAPIView):
    permission_required = ViewClassPermission(
        GET=all_permissions.storages_view,
        POST=all_permissions.storages_change,
    )
    parser_classes = (JSONParser, FormParser, MultiPartParser)

    serializer_class = ImportStorageSerializer

    def get_queryset(self):
        project_pk = self.request.query_params.get('project')
        if not project_pk:
            raise ValidationError('query parameter "project" is required')

        project = generics.get_object_or_404(Project, pk=project_pk)
        self.check_object_permissions(self.request, project)
        StorageClass = self.serializer_class.Meta.model
        storages = StorageClass.objects.filter(project_id=project.id)

        # check failed jobs and sync their statuses
        StorageClass.ensure_storage_statuses(storages)
        return storages

    def perform_create(self, serializer):
        from rest_framework.exceptions import PermissionDenied

        project = serializer.validated_data.get('project')
        if project is not None and not project.has_permission(self.request.user):
            raise PermissionDenied('You do not have permission to create storages for this project.')
        super().perform_create(serializer)

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Append ?project=<project_id> to the storage list request.
  2. Ensure the frontend/SDK has the project id available before calling the storages endpoint.
  3. Return a clearer client-side error if project id is missing before issuing the request.
  4. If you own the API, consider using a nested route (/api/projects/<id>/storages/) for discoverability.

Example fix

// before
fetch('/api/storages/')
// after
fetch(`/api/storages/?project=${projectId}`)
Defensive patterns

Strategy: validation

Validate before calling

params = {'project': project_id}
if not project_id:
    raise ValueError('project id must be provided before listing storages')
requests.get('/api/storages/', params=params)

Type guard

def has_project_filter(query: dict) -> bool:
    v = query.get('project')
    return isinstance(v, (str, int)) and str(v).strip() != ''

Try / catch

try:
    storages = client.import_storage.list(project_id=pid)
except ValidationError as e:
    if 'project' in str(e):
        raise UsageError('Storages endpoint requires ?project=<id>') from e
    raise

Prevention

When it happens

Trigger: GET /api/storages/ (import or export storage list endpoints) without ?project=<id>, or with project= empty.

Common situations: SDK/API clients omitting the project filter; older clients using a path parameter after the API changed to query-param based; UI code constructing the URL without the selected project id.

Related errors


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