{"record":{"id":"d0bbaec56fbb6833","repo":"HumanSignal/label-studio","slug":"invalid-entity-name-entity-name","errorCode":null,"errorMessage":"Invalid entity name: {entity_name}","messagePattern":"Invalid entity name: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":500,"severity":"error","filePath":"label_studio/fsm/api.py","lineNumber":34,"sourceCode":")\nfrom fsm.state_manager import get_state_manager\nfrom fsm.transitions import ModelChangeTransition, TransitionValidationError\nfrom pydantic import ValidationError as PydanticValidationError\nfrom rest_framework import generics, status\nfrom rest_framework.exceptions import NotFound, PermissionDenied, ValidationError\nfrom rest_framework.filters import OrderingFilter\nfrom rest_framework.pagination import PageNumberPagination\nfrom rest_framework.response import Response\n\nlogger = logging.getLogger(__name__)\n\n\nclass FSMAPIMixin:\n    def get_permission_required(self):\n        entity_name = self.kwargs['entity_name']\n        permission = self.permission_map.get(entity_name)\n        if not permission:\n            raise ValueError(f'Invalid entity name: {entity_name}')\n        return permission\n\n    def get_entity(self):\n        state_model = get_state_model(self.kwargs['entity_name'])\n        if not state_model:\n            raise NotFound()\n        entity_model = state_model.get_entity_model()\n        entity = get_object_or_404(entity_model.objects, id=self.kwargs['entity_id'])\n        try:\n            self.check_object_permissions(self.request, entity)\n        except PermissionDenied as e:\n            # Return 404 instead of 403 to avoid leaking entity existence\n            raise NotFound() from e\n        return entity\n\n\nclass FSMEntityHistoryPagination(PageNumberPagination):\n    page_size_query_param = 'page_size'","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/fsm/api.py#L16-L52","documentation":"FSMAPIMixin.get_permission_required looks up the URL kwarg entity_name in the view's permission_map and raises ValueError(f'Invalid entity name: {entity_name}') when there is no entry. This is a configuration/routing error: the FSM endpoint was called with an entity name that has no permission mapping registered.","triggerScenarios":"Requesting any FSM mixin endpoint (e.g. history list/transition endpoints) with an entity_name URL segment that is not a key of the view class's permission_map — e.g. a typo or an entity type that was never registered on that view.","commonSituations":"Hardcoded client URLs referencing renamed entities; a new state model was registered in state_model_registry but permission_map on the view was not updated; typos in route parameters (e.g. 'taskss' vs 'task'); API version drift between frontend and backend.","solutions":["Correct the entity_name in the request URL to a registered entity (e.g. 'task').","Add the missing entity_name -> permission entry to the view's permission_map.","Verify state_model_registry registrations match the permission_map keys.","Add a route/serializer validation or a friendly 404 for unknown entity_name before permission lookup.","Update client code/tests that hardcode old entity names."],"exampleFix":"// before\nclass FSMHistoryView(FSMAPIMixin):\n    permission_map = {\"task\": all_permissions.tasks_view}  # request uses entity_name=\"annotation\"\n// after\nclass FSMHistoryView(FSMAPIMixin):\n    permission_map = {\"task\": all_permissions.tasks_view, \"annotation\": all_permissions.annotations_view}","handlingStrategy":"validation","validationCode":"def entity_is_configured(entity_name: str, permission_map: dict, registry) -> bool:\n    return entity_name in permission_map and entity_name in registry.get_all_models()","typeGuard":null,"tryCatchPattern":"try:\n    perm = view.get_permission_required()\nexcept ValueError as e:\n    logger.error('FSM entity misconfigured: %s', e)\n    return Response({'detail': f'Unknown entity: {view.kwargs[\"entity_name\"]}'}, status=404)","preventionTips":["Derive permission_map keys from state_model_registry so they cannot drift","Add a startup assertion that registry keys == permission_map keys","Use constants/shared types for entity names across client and server","Cover every registered entity with an API test"],"tags":["django","fsm","configuration","api"],"backgroundTag":"invalid-entity-name","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}