HumanSignal/label-studio · error · ValidationError

Incorrect format {type(result)} for prediction result {resul

Error message

Incorrect format {type(result)} for prediction result {result}

What it means

Prediction.prepare_prediction_result() received a result that is neither a list nor a dict nor a supported scalar (str/int/float for single-value tags), so it cannot be interpreted. ValidationError names the offending Python type and raw value. Only those shapes have defined parsing rules; anything else (e.g. None, bool, tuple, nested nonsense) is rejected.

Source

Thrown at label_studio/tasks/models.py:1159

                            'value': result,
                        }
                    ]

        elif isinstance(result, (str, numbers.Integral)):
            # If result is of integral type, it could be a representation of data from single-valued control tags (e.g. Choices, Rating, etc.)
            for tag, tag_info in project.get_parsed_config().items():
                tag_type = tag_info['type'].lower()
                if tag_type in SINGLE_VALUED_TAGS and isinstance(result, SINGLE_VALUED_TAGS[tag_type]):
                    return [
                        {
                            'from_name': tag,
                            'to_name': ','.join(tag_info['to_name']),
                            'type': tag_type,
                            'value': {tag_type: [result]},
                        }
                    ]
        else:
            raise ValidationError(f'Incorrect format {type(result)} for prediction result {result}')

    def update_task(self):
        update_fields = ['updated_at']

        # updated_by
        request = get_current_request()
        if request:
            self.task.updated_by = request.user
            update_fields.append('updated_by')

        self.task.save(update_fields=update_fields, skip_fsm=True)

    def save(self, *args, update_fields=None, **kwargs):
        if self.project_id is None and self.task_id:
            logger.warning('project_id is not set for prediction, project_id being set in save method')
            self.project_id = Task.objects.only('project_id').get(pk=self.task_id).project_id
            if update_fields is not None:
                update_fields = {'project_id'}.union(update_fields)

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Ensure result is always a list of region dicts, a dict, or a single scalar (string/number) before creating the Prediction
  2. Handle empty/failed model responses explicitly: skip creating the prediction or use a valid empty list []
  3. Log/inspect the raw backend output to find where None or a tuple is produced
  4. Coerce types at the boundary, e.g. result = list(result) if isinstance(result, tuple) else result

Example fix

// before
pred = model.predict(data)  # may return None
Prediction.objects.create(task=task, result=pred)
// after
pred = model.predict(data)
if not pred:
    return  # or raise/log upstream
Prediction.objects.create(task=task, result=pred)
Defensive patterns

Strategy: type-guard

Validate before calling

def ensure_supported_result_type(result):
    if result is None or isinstance(result, (bool, tuple, set)):
        raise ValueError(f"unsupported prediction result type {type(result).__name__}")
    return result

Type guard

def has_supported_result_type(result) -> bool:
    if isinstance(result, (str, int, float)) and not isinstance(result, bool):
        return True
    if isinstance(result, list):
        return all(isinstance(i, dict) for i in result)
    return isinstance(result, dict)

Try / catch

from rest_framework.exceptions import ValidationError
try:
    Prediction.objects.create(task=task, result=pred)
except ValidationError:
    logger.warning("dropping malformed prediction (type=%s)", type(pred).__name__)
    return None

Prevention

When it happens

Trigger: Passing result=None, result=(...), a boolean, or any non-JSON-serializable/unsupported object when creating/updating a Prediction via the model save path, _create_memory_efficient/_create_legacy, or add_predictions; typically from a bug in the caller (model returned None and the code forwarded it).

Common situations: ML backend returning null predictions on failure that get stored verbatim; deserialized JSON where the result key is null; tuples from Python code passed straight in; type confusion between predictions and annotations fields.

Related errors


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