HumanSignal/label-studio · error · ValidationError

Value must be a list

Error message

Value must be a list

What it means

DRF ValidationError from validate_string_list raised when the value is not a Python list (e.g. a comma-separated string, dict, or scalar). The validator checks type after the emptiness check.

Source

Thrown at label_studio/ml_models/models.py:27

from ml_model_providers.models import ModelProviderConnection, ModelProviders
from projects.models import Project
from rest_framework.exceptions import ValidationError
from tasks.models import Annotation, FailedPrediction, Prediction, PredictionMeta

logger = logging.getLogger(__name__)


# skills are partitions of projects (label config + input columns + output columns) into categories of labeling tasks
class SkillNames(models.TextChoices):
    TEXT_CLASSIFICATION = 'TextClassification', _('TextClassification')
    NAMED_ENTITY_RECOGNITION = 'NamedEntityRecognition', _('NamedEntityRecognition')


def validate_string_list(value):
    if not value:
        raise ValidationError('list should not be empty')
    if not isinstance(value, list):
        raise ValidationError('Value must be a list')
    if not all(isinstance(item, str) for item in value):
        raise ValidationError('All items in the list must be strings')


class ModelInterface(models.Model):
    title = models.CharField(_('title'), max_length=500, null=False, blank=False, help_text='Model name')

    description = models.TextField(_('description'), null=True, blank=True, help_text='Model description')

    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL, related_name='created_models', on_delete=models.SET_NULL, null=True
    )

    created_at = models.DateTimeField(_('created at'), auto_now_add=True)

    updated_at = models.DateTimeField(_('updated at'), auto_now=True)

    organization = models.ForeignKey(

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Send the value as a JSON array, e.g. ["a","b"] instead of "a,b"
  2. Split strings client-side before submission
  3. Align the ML backend's returned interface format with the expected list schema

Example fix

// before
{"labels": "class_a,class_b"}
// after
{"labels": ["class_a", "class_b"]}
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(value, list):
    if isinstance(value, str):
        value = value.split(',')  # coerce common string form

Type guard

def is_str_list(v) -> bool:
    return isinstance(v, list)

Try / catch

try:
    interface.full_clean()
except ValidationError as e:
    if 'Value must be a list' in str(e):
        value = [s.strip() for s in str(value).split(',')]

Prevention

When it happens

Trigger: Submitting a ModelInterface field as a string like "a,b" or a JSON object instead of a JSON array when creating/updating an ML model interface.

Common situations: Sending comma-separated strings from clients; JSON schema mismatch between ML backend and Label Studio; YAML/JSON config parsing producing a dict instead of a list.

Related errors


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