HumanSignal/label-studio · error · ValidationError

Enter a valid {value_type.lower()} value.

Error message

Enter a valid {value_type.lower()} value.

What it means

After validation, the raw value is coerced with the callable mapped from value_type ({'String': str, 'Number': float, 'Expression': str}). If the conversion raises TypeError or ValueError, ValidationError {'value': 'Enter a valid <value_type> value.'} is raised. Most commonly a non-numeric string was supplied for value_type 'Number'.

Source

Thrown at label_studio/data_manager/actions/data_columns.py:54

    if not isinstance(value_name, str) or not value_name.strip():
        raise ValidationError({'column_name': 'Select an existing column or enter a new column name.'})

    value_name = value_name.strip()
    column_exists = value_name in project.summary.all_data_columns
    if not column_exists:
        column_exists = project.tasks.filter(data__has_key=value_name).exists()
    mode = 'update' if column_exists else 'add'
    # Existing columns (e.g. imported spreadsheet headers) stay editable, but a new column must be
    # one the Data Manager can filter and sort on.
    if mode == 'add' and not is_queryable_column_name(value_name):
        raise ValidationError(
            {'column_name': f'Column name cannot contain {UNQUERYABLE_COLUMN_NAME_CHARACTERS}.'},
        )
    try:
        value = {'String': str, 'Number': float, 'Expression': str}[value_type](value)
    except (TypeError, ValueError) as exc:
        raise ValidationError({'value': f'Enter a valid {value_type.lower()} value.'}) from exc

    return mode, value_name, value_type, value


def _set_data_value_in_batches(queryset, value_name, postgres_value, sqlite_value):
    if settings.DJANGO_DB == settings.DJANGO_DB_SQLITE:
        updated_count = 0
        task_iterator = iterate_queryset(queryset.only('id', 'data'), chunk_size=settings.UPDATE_COLUMN_BATCH_SIZE)
        for task_batch in batched_iterator(task_iterator, settings.UPDATE_COLUMN_BATCH_SIZE):
            for task in task_batch:
                task.data = task.data or {}
                task.data[value_name] = sqlite_value(task)
            Task.objects.bulk_update(task_batch, fields=['data'], batch_size=settings.UPDATE_COLUMN_BATCH_SIZE)
            updated_count += len(task_batch)
        return updated_count

    updated_count = 0
    task_iterator = iterate_queryset(queryset.only('id', 'project_id'), chunk_size=settings.UPDATE_COLUMN_BATCH_SIZE)

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Provide a value convertible to float when value_type is 'Number' (e.g. '42' or '3.14').
  2. Use value_type 'String' for non-numeric text.
  3. Convert empty/None values to a suitable default before submitting.

Example fix

// before
{'value_type': 'Number', 'value': '12,5', 'column_name': 'score'}
// after
{'value_type': 'Number', 'value': '12.5', 'column_name': 'score'}
Defensive patterns

Strategy: validation

Validate before calling

vt = request_data.get('value_type', 'String')
raw = request_data.get('value', '')
if vt == 'Number':
    float(raw)  # raises before the API call if not numeric

Type guard

def is_coercible(value, value_type):
    try:
        {'String': str, 'Number': float, 'Expression': str}[value_type](value)
        return True
    except (TypeError, ValueError):
        return False

Try / catch

from rest_framework.exceptions import ValidationError
try:
    add_data_field(project, qs, request=request)
except ValidationError as e:
    if 'value' in e.message_dict:
        show_value_type_hint(e.message_dict['value'])

Prevention

When it happens

Trigger: value_type 'Number' with value 'abc' or '' (float('abc') raises ValueError); value None for a Number column (float(None) raises TypeError).

Common situations: Spreadsheet cell containing text mapped to a Number column; locale-formatted numbers with commas ('1,5'); empty CSV cells submitted as empty strings.

Related errors


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