{"record":{"id":"e174dee7936128b5","repo":"HumanSignal/label-studio","slug":"invalid-or-missing-serializer-class","errorCode":null,"errorMessage":"Invalid or missing serializer class","messagePattern":"Invalid or missing serializer class","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"label_studio/io_storages/functions.py","lineNumber":38,"sourceCode":"    Preload and prepare a storage instance from request data.\n\n    This function handles the common logic for loading existing storage instances\n    or creating new ones from request data, including permission checks and\n    serializer validation.\n\n    Args:\n        request: The HTTP request containing storage data\n        serializer_class: The serializer class to use for validation\n\n    Returns:\n        The prepared storage instance\n\n    Raises:\n        PermissionDenied: If user doesn't have permission to access the storage\n        ValidationError: If serializer validation fails\n    \"\"\"\n    if not serializer_class or not hasattr(serializer_class, 'Meta'):\n        raise ValidationError('Invalid or missing serializer class')\n\n    storage_id = request.data.get('id')\n    instance = None\n\n    if storage_id:\n        instance = get_object_or_404(serializer_class.Meta.model.objects.all(), pk=storage_id)\n        if not instance.has_permission(request.user):\n            raise PermissionDenied()\n\n    # combine instance fields with request.data\n    serializer = serializer_class(data=request.data)\n    serializer.is_valid(raise_exception=True)\n\n    # if storage exists, we have to use instance from DB,\n    # because instance from serializer won't have credentials, they were popped intentionally\n    if instance:\n        instance = serializer.update(instance, serializer.validated_data)\n    else:","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/io_storages/functions.py#L20-L56","documentation":"validate_storage_instance raises ValidationError when the passed serializer_class is None/empty or lacks a Meta attribute, meaning the storage endpoint was wired with an unknown or wrong storage type before any DB lookup happens.","triggerScenarios":"Calling create() (the storage API view) for a storage type whose serializer class could not be resolved (get_storage_list mismatch, unsupported/removed storage type in the URL path, a coding error passing the wrong class).","commonSituations":"Registering a custom storage but forgetting to add its serializer to get_storage_list(); typos in storage type in the API request; a plugin/older storage type removed after an upgrade.","solutions":["Ensure the storage type in the request maps to a registered serializer in io_storages/functions.py get_storage_list()","Verify the custom storage's serializer subclasses ImportStorageSerializer/ExportStorageSerializer and defines Meta with model","If you hit this from a custom view, pass the correct serializer_class to validate_storage_instance","After adding a new storage type, restart the server so the registry is rebuilt"],"exampleFix":"// before (custom storage not registered)\nclass MyStorageSerializer:  # no Meta\n    class Meta: pass  # missing model\n// after\nfrom label_studio.io_storages.serializers import ImportStorageSerializer\nclass MyStorageSerializer(ImportStorageSerializer):\n    class Meta:\n        model = MyStorage\n        fields = '__all__'","handlingStrategy":"validation","validationCode":"def serializer_is_usable(serializer_class):\n    return bool(serializer_class) and hasattr(serializer_class, 'Meta') and getattr(serializer_class.Meta, 'model', None) is not None","typeGuard":"def is_drf_serializer(cls):\n    return isinstance(cls, type) and hasattr(cls, 'Meta') and hasattr(cls.Meta, 'model')","tryCatchPattern":"from rest_framework.exceptions import ValidationError\ntry:\n    instance = validate_storage_instance(request, serializer_class)\nexcept ValidationError as e:\n    logger.error('Bad storage serializer wiring: %s', e.detail)","preventionTips":["Register every custom storage serializer in get_storage_list()","Subclass ImportStorageSerializer/ExportStorageSerializer and define Meta.model","Send a supported storage type in the API path","Restart the server after changing the storage registry"],"tags":["api","drf","configuration","validation"],"backgroundTag":"invalid-serializer-config","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}