{"record":{"id":"a7a8400310894dbb","repo":"HumanSignal/label-studio","slug":"validation-errors","errorCode":null,"errorMessage":"validation_errors","messagePattern":"validation_errors","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"label_studio/data_import/api.py","lineNumber":665,"sourceCode":"            # If prediction is valid, add it to predictions list to be created\n            try:\n                predictions.append(\n                    Prediction(\n                        task_id=item['task'],\n                        project_id=project.id,\n                        result=Prediction.prepare_prediction_result(item.get('result'), project),\n                        score=item.get('score'),\n                        model_version=item.get('model_version', 'undefined'),\n                    )\n                )\n            except Exception as e:\n                validation_errors.append(f'Prediction {i}: Failed to create prediction - {extract_message(e)}')\n                continue\n\n        # If there are validation errors, raise them before creating any predictions\n        if validation_errors:\n            if flag_set('fflag_feat_utc_210_prediction_validation_15082025', user='auto'):\n                raise ValidationError(validation_errors)\n            else:\n                logger.error(f'Prediction validation failed ({len(validation_errors)} errors):\\n{validation_errors}')\n\n        predictions_obj = Prediction.objects.bulk_create(predictions, batch_size=settings.BATCH_SIZE)\n        start_job_async_or_sync(update_tasks_counters, Task.objects.filter(id__in=tasks_ids))\n        return Response({'created': len(predictions_obj)}, status=status.HTTP_201_CREATED)\n\n\n@extend_schema(exclude=True)\nclass TasksBulkCreateAPI(ImportAPI):\n    # just for compatibility - can be safely removed\n    pass\n\n\nclass ReImportAPI(ImportAPI):\n    permission_required = all_permissions.projects_change\n\n    def sync_reimport(self, project, file_upload_ids, files_as_tasks_list):","sourceCodeStart":647,"sourceCodeEnd":683,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/data_import/api.py#L647-L683","documentation":"At the end of _create_legacy, all validation errors collected while iterating prediction items are raised together as ValidationError(validation_errors) when the prediction-validation feature flag is enabled; otherwise they are only logged. This blocks prediction creation so invalid items cannot be silently skipped.","triggerScenarios":"POSTing multiple predictions where at least one fails validation (invalid task ID, failed creation, label-config mismatch). Aggregated errors are raised pre-create when fflag_feat_utc_210_prediction_validation_15082025 is set.","commonSituations":"Bulk prediction re-imports after label config changes; exports containing items whose tasks were deleted; behavior change after enabling the flag — previously logged-and-skipped items now abort the whole request with an error array.","solutions":["Parse the returned array; each entry is prefixed with 'Prediction {i}:' identifying the failing item","Fix the listed items and resubmit","Pre-validate task IDs and label config compatibility before sending the payload","If behavior change is unacceptable, disable the feature flag (legacy: errors logged, bad items skipped) — not recommended","Filter predictions to only those passing validation client-side before import"],"exampleFix":"# before: send everything, get array failure\nresp = requests.post(url, json=predictions)\n# after: validate per-item against task existence first\nexisting = {t['id'] for t in get_tasks(project_id)}\nclean = [p for p in predictions if p.get('task') in existing]\nresp = requests.post(url, json=clean)","handlingStrategy":"try-catch","validationCode":"existing_ids = {t['id'] for t in paginate(f'{LS}/api/projects/{pid}/tasks')}\nclean = [p for p in predictions if p.get('task') in existing_ids]\nassert clean == predictions, 'some predictions reference missing tasks and will fail validation'","typeGuard":null,"tryCatchPattern":"try:\n    resp = requests.post(import_url, headers=H, json=predictions)\n    resp.raise_for_status()\nexcept requests.HTTPError as e:\n    errors = e.response.json()\n    if isinstance(errors, list):\n        bad_idx = {int(m.split(':')[1].strip().replace('Prediction ', '')) for m in errors if m.startswith('Prediction ')}\n        log.error('Failing prediction indices: %s', sorted(bad_idx))","preventionTips":["Track whether the prediction-validation flag is enabled; behavior differs (raise vs log)","Pre-filter predictions against existing task IDs","Keep exports and their source projects in sync; re-export after config or task deletions"],"tags":["django","rest-framework","predictions","validation","feature-flag"],"backgroundTag":"schema-validation-failed","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}