HumanSignal/label-studio · error · ValidationError

Column name cannot contain {UNQUERYABLE_COLUMN_NAME_CHARACTE

Error message

Column name cannot contain {UNQUERYABLE_COLUMN_NAME_CHARACTERS}.

What it means

For a NEW column (mode 'add'), the name must pass is_queryable_column_name — it must be filterable/sortable by the Data Manager. Names containing characters in UNQUERYABLE_COLUMN_NAME_CHARACTERS (e.g. dots/dollar signs used by nested JSON paths) are rejected with ValidationError {'column_name': 'Column name cannot contain ...'}. Existing columns (e.g. imported spreadsheet headers) are exempt and stay editable.

Source

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

    )
    value_type = request_data.get('value_type', 'String')
    value = request_data.get('value', '')

    if value_type not in {'String', 'Number', 'Expression'}:
        raise ValidationError({'value_type': 'Choose a supported column type.'})

    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)

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Rename the new column to exclude unqueryable characters (use '_' instead of '.').
  2. If the column already exists in task data, it is treated as 'update' mode and allowed — verify the exact name matches the existing key.
  3. Sanitize generated column names before calling the action.

Example fix

// before
column_name = 'user.email'
// after
column_name = 'user_email'
Defensive patterns

Strategy: validation

Validate before calling

import re
FORBIDDEN = set('.$[]{}"\\ *?<>|,:;/')  # mirror UNQUERYABLE_COLUMN_NAME_CHARACTERS
def assert_queryable_new_column(name, existing_columns):
    if name in existing_columns:
        return
    bad = [c for c in name if c in FORBIDDEN]
    assert not bad, f'column name contains unqueryable characters: {bad}'

Type guard

def is_safe_column_name(name):
    return isinstance(name, str) and bool(name.strip()) and not any(ch in name for ch in '.$[]"\\')

Try / catch

from rest_framework.exceptions import ValidationError
try:
    add_data_field(project, qs, request=request)
except ValidationError as e:
    if 'column_name' in e.message_dict and 'cannot contain' in str(e):
        sanitize_and_retry()

Prevention

When it happens

Trigger: Adding a column whose name contains characters like '.' or '$', e.g. column_name 'user.email' when that column does not already exist in project data.

Common situations: Trying to create nested-path style columns ('a.b') mimicking existing dotted keys; spreadsheet headers with dots when re-importing; automation generating column names with dots/dollars.

Related errors


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