HumanSignal/label-studio · error · ValidationError

All items in the list must be strings

Error message

All items in the list must be strings

What it means

DRF ValidationError from validate_string_list raised when every element check fails: the list contains non-string items (ints, dicts, nulls, etc.).

Source

Thrown at label_studio/ml_models/models.py:29

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(
        'organizations.Organization', on_delete=models.CASCADE, related_name='model_interfaces', null=True
    )

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Convert items to strings before submission (map str(item))
  2. Fix the ML backend to return string values for the interface lists
  3. Coerce in the serializer/model if numeric ids should be accepted

Example fix

// before
{"labels": [1, 2, 3]}
// after
{"labels": ["1", "2", "3"]}
Defensive patterns

Strategy: type-guard

Validate before calling

if not all(isinstance(i, str) for i in value):
    value = [str(i) for i in value]

Type guard

def all_strings(v: list) -> bool:
    return isinstance(v, list) and all(isinstance(i, str) for i in v)

Try / catch

try:
    interface.full_clean()
except ValidationError as e:
    if 'must be strings' in str(e):
        interface.labels = [str(x) for x in interface.labels]
        interface.full_clean()

Prevention

When it happens

Trigger: Submitting a list like [1,2,3] or [{...}] for a ModelInterface list field that must contain only strings.

Common situations: ML backend returning enum codes/ints instead of string names; clients sending numeric ids for labels or controls; JSON payloads with mixed types.

Related errors


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