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 LabelInterface

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Include the task (or project) in the request payload, e.g. PATCH {"task": <task_id>, "result": [...]}
  2. 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)
  3. 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

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


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