HumanSignal/label-studio · error · ValidationError
Task item should be dict
Error message
Task item should be dict
What it means
Label Studio's read_tasks_list_from_json normalizes each imported JSON task so that it has a 'data' key holding a dict. When a task's resolved 'data' payload is not a dict (e.g. a string or number), it raises this ValidationError because tasks must map column keys to values.
Source
Thrown at label_studio/data_import/models.py:166
return tasks
def read_tasks_list_from_json(self):
logger.debug('Read tasks list from JSON file {}'.format(self.filepath))
raw_data = self.content
# Python 3.5 compatibility fix https://docs.python.org/3/whatsnew/3.6.html#json
try:
tasks = json.loads(raw_data)
except TypeError:
tasks = json.loads(raw_data.decode('utf8'))
if isinstance(tasks, dict):
tasks = [tasks]
tasks_formatted = []
for i, task in enumerate(tasks):
if not task.get('data'):
task = {'data': task}
if not isinstance(task['data'], dict):
raise ValidationError('Task item should be dict')
tasks_formatted.append(task)
return tasks_formatted
def read_tasks_list_from_json_streaming(self, batch_size=100):
logger.debug('Read tasks list from JSON file streaming {}'.format(self.filepath))
try:
with self.file.open('rb') as file_handle:
# Peek a small prefix to detect top-level container ('[' array or '{' object)
sniff = file_handle.read(4096) or b''
# Find first non-whitespace byte
first_byte = None
for b in sniff:
if b not in (0x20, 0x09, 0x0A, 0x0D): # space, tab, lf, cr
first_byte = b
break
# Rewind after sniffingView on GitHub (pinned to 0b49e9b539)
Solutions
- Wrap each item as an object with a $undefined_key or your data key, e.g. [{"data": {"text": "a"}}]
- Re-export the file so each element is a JSON object with key/value fields
- Validate the JSON structure before upload (every element is an object)
Example fix
// before (tasks.json)
["first text", "second text"]
// after
[{"data": {"text": "first text"}}, {"data": {"text": "second text"}}] Defensive patterns
Strategy: validation
Validate before calling
import json
with open('tasks.json') as f:
tasks = json.load(f)
if isinstance(tasks, dict):
tasks = [tasks]
for t in tasks:
data = t.get('data') if isinstance(t, dict) else t
if not isinstance(data, dict):
raise ValueError(f"Task data must be a dict, got {type(data).__name__}") Type guard
def is_valid_task(item):
if isinstance(item, dict):
return isinstance(item.get('data'), dict)
return isinstance(item, dict)
valid = [t for t in tasks if is_valid_task(t)] Try / catch
from rest_framework.exceptions import ValidationError
try:
tasks = fu.read_tasks()
except ValidationError as e:
logger.error("Task structure invalid: %s", e)
# fix file or skip Prevention
- Export tasks as JSON objects with explicit data keys
- Validate JSON structure with a schema before import
- Never upload arrays of scalars as .json; use .txt instead
When it happens
Trigger: Calling read_tasks (via FileUpload.read_tasks or load_tasks_from_uploaded_files) with a .json file whose top-level array (or object) yields elements whose data is a non-dict, e.g. a JSON file containing ["a","b"] where each bare string becomes data.
Common situations: Uploading a JSON file of plain strings or numbers instead of objects; exporting from another tool into a flat JSON array of scalars; hand-edited JSON where the object wrapper was lost.
Related errors
- Unsupported or invalid JSON structure
- Failed to parse JSON file {self.file_name}: {extract_message
- Your label config has more than one data key and direct file
- annotation "result" can't be parse from str to JSON
- not_a_list
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/240e5635cdd5038a.
Report an issue: GitHub.