HumanSignal/label-studio · error · ValidationError
Project is required for prediction validation
Error message
Project is required for prediction validation
What it means
PredictionSerializer.validate() validates the prediction's result against the project's labeling configuration, which requires resolving the related Project from data['task'].project or data['project']. When the payload updates 'result' but contains neither a task nor a project, the validator raises ValidationError because it has no label config to validate against.
Source
Thrown at label_studio/tasks/serializers.py:112
'select specific model version for showing preannotations in the labeling interface',
)
created_ago = serializers.CharField(default='', read_only=True, help_text='Delta time from creation time')
def validate(self, data):
"""Validate prediction using LabelInterface against project configuration"""
project = None
if 'task' in data:
project = data['task'].project
elif 'project' in data:
project = data['project']
ff_user = project.organization.created_by if project else 'auto'
# Only validate if we're updating the result field
if 'result' not in data:
return data
if not project:
raise ValidationError('Project is required for prediction validation')
custom_interface_validator = load_func(getattr(settings, 'CUSTOM_INTERFACE_PREDICTION_VALIDATOR', None))
if custom_interface_validator:
validation_errors = custom_interface_validator(project, data.get('result', []))
if validation_errors:
raise ValidationError(f'Error validating prediction: {validation_errors}')
if not flag_set('fflag_feat_utc_210_prediction_validation_15082025', user=ff_user):
# Skip validation if feature flag is not set
logger.info(f'Skipping prediction validation in PredictionSerializer for user {ff_user}')
return super().validate(data)
# Custom Interface projects normally keep the default <View></View>
# label_config and are validated above against output_schema instead.
if not project.label_config_is_not_default:
return super().validate(data)
# Validate prediction using LabelInterfaceView on GitHub (pinned to 0b49e9b539)
Solutions
- Include the task (or project) in the request payload, e.g. PATCH {"task": <task_id>, "result": [...]}
- Pass the existing prediction's task via serializer context or instance so project can be resolved (self.instance.project is used in AnnotationSerializer; ensure PredictionSerializer is called with the instance)
- If updating standalone, first fetch the prediction and supply project= prediction.task.project in serializer data/context
Example fix
// before
requests.patch(f"/api/predictions/{pid}/", json={"result": result})
// after
requests.patch(f"/api/predictions/{pid}/", json={"task": task_id, "result": result}) Defensive patterns
Strategy: validation
Validate before calling
def assert_payload_has_project(payload):
if 'result' in payload and 'task' not in payload and 'project' not in payload:
raise ValueError("updating 'result' requires 'task' or 'project' in the payload for validation") Type guard
def can_validate_prediction(data: dict) -> bool:
return ('result' not in data) or ('task' in data or 'project' in data) Try / catch
from rest_framework.exceptions import ValidationError
try:
ser = PredictionSerializer(instance=prediction, data={"result": result}, partial=True)
ser.is_valid(raise_exception=True)
except ValidationError as e:
logger.error("prediction update rejected: %s", e) # likely missing task/project Prevention
- Always include task (or project) when PATCHing prediction results
- When using the serializer directly, supply the instance so the project can be resolved via context/instance
- Never build partial prediction payloads that drop the task FK
- In bulk-update scripts, fetch each prediction and pass its task_id along with the new result
When it happens
Trigger: PATCH/PUT to the predictions API updating only the result field without including task (e.g. no task PK in the request, or task not passed in serializer context) so neither data['task'] nor data['project'] is present.
Common situations: Client scripts PATCHing /api/predictions/<id>/ with only {"result": [...]}; bulk update utilities that drop task from the payload; custom code using the serializer directly with partial data and an empty context.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Each item in prediction result should be dict
- {connection validation error}
- exc.kwargs['report']
- Wrong credentials for S3 {bucket_name}
- list should not be empty
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/6f740451d194c77b.
Report an issue: GitHub.