HumanSignal/label-studio · error · ValidationError
data['{data_key}']={data_value} is of type '{type}', but the
Error message
data['{data_key}']={data_value} is of type '{type}', but the object tag {data_type} expects the following types: {expected_types} What it means
After finding the required key, check_data validates its value's Python type against _DATA_TYPES, which maps each labeling-config object tag (Text, Image, HyperText, ...) to allowed types. This error means the key exists but its value's type is not allowed for the tag used in the config, e.g. a dict where Text expects str/int/float/list. Bracketed array tags (from Repeater, is_array=True) require a list.
Source
Thrown at label_studio/tasks/validation.py:85
if '.' in data_key:
keys = data_key.split('.')
try:
data_item = reduce(getitem, keys, data)
except KeyError:
raise ValidationError('"{data_key}" key is expected in task data'.format(data_key=data_key))
else:
if data_key not in data:
raise ValidationError('"{data_key}" key is expected in task data'.format(data_key=data_key))
data_item = data[data_key]
if is_array:
expected_types = (list,)
else:
expected_types = _DATA_TYPES.get(data_type, (str,))
if not isinstance(data_item, tuple(expected_types)):
raise ValidationError(
"data['{data_key}']={data_value} is of type '{type}', "
'but the object tag {data_type} expects the following types: {expected_types}'.format(
data_key=data_key,
data_value=data_item,
type=type(data_item).__name__,
data_type=data_type,
expected_types=[e.__name__ for e in expected_types],
)
)
return data
@staticmethod
def check_data_and_root(project, data, dict_is_root=False):
"""Check data consistent and data is dict with task or dict['task'] is task
:param project:
:param data:View on GitHub (pinned to 0b49e9b539)
Solutions
- Coerce the value to a type allowed by the tag (e.g. str(value) for Text, list for Repeater variables)
- Check _DATA_TYPES to see the accepted types for the tag used in your config
- If the config uses a bracketed/Repeater variable ($items), wrap the value in a list
- If you need richer payloads, use a tag that accepts dict (Table, TimeSeries) or upload the object as a file/reference
Example fix
// before
{'data': {'text': {'body': 'hello'}}} # <Text value="$text"/>
// after
{'data': {'text': str({'body': 'hello'})}} # or use a Table/TimeSeries tag that accepts dict Defensive patterns
Strategy: type-guard
Validate before calling
_DATA_TYPES = {'Text': (str, int, float, list), 'Image': (str, list)}
for key, tag in project.data_types.items():
key = key.split('[')[0]
if key in data and not isinstance(data[key], tuple(_DATA_TYPES.get(tag, (str,)))):
raise TypeError(f'{key} must match tag {tag}') Type guard
def matches_tag(value, tag, is_array=False):
expected = (list,) if is_array else tuple(_DATA_TYPES.get(tag, (str,)))
return isinstance(value, expected) Try / catch
try:
import_tasks(tasks)
except ValidationError as e:
m = re.search(r"data\['(.+?)'\].*tag (\w+)", str(e.detail[0]))
if m:
coerce_value(tasks, m.group(1), m.group(2)) Prevention
- Consult _DATA_TYPES when choosing a tag for a field
- Wrap values in lists for Repeater/bracket ($items) variables
- Avoid passing dicts to Text/Image-type tags; use Table/TimeSeries tags for structured data
When it happens
Trigger: Config <Image value="$img"/> with data {'img': {'url': ...}} (dict, only str|list allowed); <Text value="$text"/> with {'text': {'a': 1}}; using $var inside a Repeater (e.g. $images) while the value is a single string instead of a list.
Common situations: Passing structured/nested objects where plain strings are expected; numbers-as-strings or booleans for Header/Text; giving a single item where the config's Repeater/bracket syntax expects an array; new tag types added to the config but not covered in _DATA_TYPES default to str-only.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Validation failed on {}: {}
- Label config contains non-unique names:
- toName="{toName}" not found in names: {sorted(names)}
- Your label config has more than one data key and direct file
- Import data contains completed_by={completed_by} which is no
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/3568a0295561d82a.
Report an issue: GitHub.