HumanSignal/label-studio · error · PermissionDenied

You do not have permission to create storages for this proje

Error message

You do not have permission to create storages for this project.

What it means

DRF PermissionDenied raised in ImportStorageListAPI.perform_create when the authenticated user lacks access to the project referenced in the request payload. Label Studio checks project.has_permission(user) before allowing a storage to be attached, so storages cannot be created for projects the user is not a member of (or lacks storages_create permission on).

Source

Thrown at label_studio/io_storages/api.py:51

        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)


class ImportStorageDetailAPI(generics.RetrieveUpdateDestroyAPIView):
    """RUD storage by pk specified in URL"""

    permission_required = ViewClassPermission(
        GET=all_permissions.storages_view,
        PATCH=all_permissions.storages_change,
        PUT=all_permissions.storages_change,
        DELETE=all_permissions.storages_change,
    )
    parser_classes = (JSONParser, FormParser, MultiPartParser)
    serializer_class = ImportStorageSerializer

    @extend_schema(exclude=True)
    def put(self, request, *args, **kwargs):
        return super(ImportStorageDetailAPI, self).put(request, *args, **kwargs)

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Log in as (or use a token for) a user who is a member of the target project with storage create permission
  2. Verify the 'project' id in the request body matches a project in the same organization as the token
  3. Grant the user a role with storages_create permission (admin/owner) on the project
  4. Check organization membership of the API token via /api/current-user/whoami

Example fix

// before
curl -X POST /api/storages/s3/ -H "Authorization: Token <user-without-access>" -d '{"project": 5, ...}'
// after
curl -X POST /api/storages/s3/ -H "Authorization: Token <project-admin-token>" -d '{"project": 5, ...}'
Defensive patterns

Strategy: validation

Validate before calling

import requests
# Check membership/permissions before POSTing a storage
r = requests.get(f"{LS_URL}/api/projects/{project_id}/", headers={"Authorization": f"Token {token}"})
if r.status_code == 404 or not r.ok:
    raise PermissionError(f"No access to project {project_id}")

Type guard

def can_access_project(resp):
    return resp.status_code == 200

Try / catch

try:
    resp = requests.post(f"{LS_URL}/api/storages/s3/", json=payload, headers=headers)
    resp.raise_for_status()
except requests.HTTPError as e:
    if resp.status_code == 403:
        # switch to a token with storages_create permission
        ...

Prevention

When it happens

Trigger: POST to an import storage list endpoint (e.g. /api/storages/<type>/) with body containing a 'project' id for a project the requesting user cannot access; project passes a valid pk but has_permission returns False (not a project member, restricted role, or anonymous token).

Common situations: Using a service/account token that belongs to a different organization than the project; sharing a project id between workspaces; a user downgraded from admin/owner to reviewer/annotator attempting to attach S3/GCS/Azure storage.

Related errors


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