{"record":{"id":"51888bf3c70375a3","repo":"HumanSignal/label-studio","slug":"creating-labels-for-different-projects-in-one-requ","errorCode":null,"errorMessage":"Creating labels for different projects in one request not allowed","messagePattern":"Creating labels for different projects in one request not allowed","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"label_studio/labels_manager/serializers.py","lineNumber":14,"sourceCode":"from django.conf import settings\nfrom django.db import transaction\nfrom projects.models import Project\nfrom rest_flex_fields import FlexFieldsModelSerializer\nfrom rest_framework import serializers\nfrom rest_framework.exceptions import ValidationError\n\nfrom .models import Label, LabelLink\n\n\nclass LabelListSerializer(serializers.ListSerializer):\n    def validate(self, items):\n        if len(set(item['project'] for item in items)) > 1:\n            raise ValidationError('Creating labels for different projects in one request not allowed')\n        return items\n\n    def create(self, validated_data):\n        \"\"\"Bulk creation objects of Label model with related LabelLink\n        reusing already existing labels\n        \"\"\"\n        from webhooks.utils import emit_webhooks_for_instance\n\n        with transaction.atomic():\n            # loading already existing labels\n            titles = [item['title'] for item in validated_data]\n            existing_labels = Label.objects.filter(\n                organization=self.context['request'].user.active_organization, title__in=titles\n            ).all()\n            existing_labels_map = {label.title: label for label in existing_labels}\n\n            # create objects for labels, that we need to create\n            labels_data = []","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/labels_manager/serializers.py#L1-L32","documentation":"DRF ValidationError raised by LabelListSerializer.validate when a bulk label-creation request mixes labels belonging to more than one project. Bulk label creation only supports a single project per request so existing labels can be reused/linked consistently.","triggerScenarios":"POSTing an array to the labels bulk-create endpoint where the 'project' field differs across items, e.g. [{\"project\":1,\"value\":\"A\"},{\"project\":2,\"value\":\"B\"}].","commonSituations":"Client scripts looping over multiple projects but batching all labels into one request; UI sending the whole label set without partitioning per project; copy-paste of payloads between projects.","solutions":["Split the payload into one request per project","Ensure all items share the same 'project' id in the array","Fix client-side batching logic to group labels by project before POSTing"],"exampleFix":"// before\npost('/api/labels/', [{\"project\":1,\"value\":\"A\"},{\"project\":2,\"value\":\"B\"}])\n// after\npost('/api/labels/', [{\"project\":1,\"value\":\"A\"}])\npost('/api/labels/', [{\"project\":2,\"value\":\"B\"}])","handlingStrategy":"validation","validationCode":"projects = {lbl['project'] for lbl in payload}\nassert len(projects) <= 1, 'Batch labels must belong to one project; split per project'","typeGuard":"def single_project(labels: list[dict]) -> bool:\n    return len({lbl.get('project') for lbl in labels}) <= 1","tryCatchPattern":"try:\n    serializer.is_valid(raise_exception=True)\n    serializer.save()\nexcept ValidationError as e:\n    if 'different projects' in str(e):\n        for project_id, group in groupby(payload, key=lambda l: l['project']):\n            post_labels(list(group))","preventionTips":["Group labels by project before any bulk POST","Validate payload shape client-side before sending","Never batch labels across projects in automation"],"tags":["validation","labels","bulk-api","drf"],"backgroundTag":"bulk-request-validation-failed","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}