{"record":{"id":"019fe18f0608731c","repo":"HumanSignal/label-studio","slug":"query-parameter-project-is-required","errorCode":null,"errorMessage":"query parameter \"project\" is required","messagePattern":"query parameter \"project\" is required","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"label_studio/io_storages/api.py","lineNumber":35,"sourceCode":"from rest_framework.parsers import FormParser, JSONParser, MultiPartParser\nfrom rest_framework.response import Response\n\nlogger = logging.getLogger(__name__)\n\n\nclass ImportStorageListAPI(generics.ListCreateAPIView):\n    permission_required = ViewClassPermission(\n        GET=all_permissions.storages_view,\n        POST=all_permissions.storages_change,\n    )\n    parser_classes = (JSONParser, FormParser, MultiPartParser)\n\n    serializer_class = ImportStorageSerializer\n\n    def get_queryset(self):\n        project_pk = self.request.query_params.get('project')\n        if not project_pk:\n            raise ValidationError('query parameter \"project\" is required')\n\n        project = generics.get_object_or_404(Project, pk=project_pk)\n        self.check_object_permissions(self.request, project)\n        StorageClass = self.serializer_class.Meta.model\n        storages = StorageClass.objects.filter(project_id=project.id)\n\n        # check failed jobs and sync their statuses\n        StorageClass.ensure_storage_statuses(storages)\n        return storages\n\n    def perform_create(self, serializer):\n        from rest_framework.exceptions import PermissionDenied\n\n        project = serializer.validated_data.get('project')\n        if project is not None and not project.has_permission(self.request.user):\n            raise PermissionDenied('You do not have permission to create storages for this project.')\n        super().perform_create(serializer)\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/io_storages/api.py#L17-L53","documentation":"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).","triggerScenarios":"GET /api/storages/ (import or export storage list endpoints) without ?project=<id>, or with project= empty.","commonSituations":"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.","solutions":["Append ?project=<project_id> to the storage list request.","Ensure the frontend/SDK has the project id available before calling the storages endpoint.","Return a clearer client-side error if project id is missing before issuing the request.","If you own the API, consider using a nested route (/api/projects/<id>/storages/) for discoverability."],"exampleFix":"// before\nfetch('/api/storages/')\n// after\nfetch(`/api/storages/?project=${projectId}`)","handlingStrategy":"validation","validationCode":"params = {'project': project_id}\nif not project_id:\n    raise ValueError('project id must be provided before listing storages')\nrequests.get('/api/storages/', params=params)","typeGuard":"def has_project_filter(query: dict) -> bool:\n    v = query.get('project')\n    return isinstance(v, (str, int)) and str(v).strip() != ''","tryCatchPattern":"try:\n    storages = client.import_storage.list(project_id=pid)\nexcept ValidationError as e:\n    if 'project' in str(e):\n        raise UsageError('Storages endpoint requires ?project=<id>') from e\n    raise","preventionTips":["Always build storage list URLs with the project id from a single source of truth.","Validate required query params in the client before issuing requests.","Prefer nested project-scoped routes to make the requirement explicit."],"tags":["api","validation","query-parameters"],"backgroundTag":"missing-required-query-param","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}