{"record":{"id":"8120c0e8ef008906","repo":"HumanSignal/label-studio","slug":"data-key-key-is-expected-in-task-data","errorCode":null,"errorMessage":"\"{data_key}\" key is expected in task data","messagePattern":"\"(.+?)\" key is expected in task data","errorType":"validation","errorClass":"ValidationError","httpStatus":400,"severity":"error","filePath":"label_studio/tasks/validation.py","lineNumber":73,"sourceCode":"    def check_data(project, data):\n        \"\"\"Validate data from task['data']\"\"\"\n        if data is None:\n            raise ValidationError('Task is empty (None)')\n\n        replace_task_data_undefined_with_config_field(data, project)\n\n        # iterate over data types from project\n        for data_key, data_type in project.data_types.items():\n            # get array name in case of Repeater tag\n            is_array = '[' in data_key\n            data_key = data_key.split('[')[0]\n\n            if '.' in data_key:\n                keys = data_key.split('.')\n                try:\n                    data_item = reduce(getitem, keys, data)\n                except KeyError:\n                    raise ValidationError('\"{data_key}\" key is expected in task data'.format(data_key=data_key))\n            else:\n                if data_key not in data:\n                    raise ValidationError('\"{data_key}\" key is expected in task data'.format(data_key=data_key))\n                data_item = data[data_key]\n\n            if is_array:\n                expected_types = (list,)\n            else:\n                expected_types = _DATA_TYPES.get(data_type, (str,))\n\n            if not isinstance(data_item, tuple(expected_types)):\n                raise ValidationError(\n                    \"data['{data_key}']={data_value} is of type '{type}', \"\n                    'but the object tag {data_type} expects the following types: {expected_types}'.format(\n                        data_key=data_key,\n                        data_value=data_item,\n                        type=type(data_item).__name__,\n                        data_type=data_type,","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/tasks/validation.py#L55-L91","documentation":"check_data iterates over project.data_types (the keys derived from the labeling config, e.g. <Text value=\"$text\"/>) and requires each named key (including dotted nested paths like 'row.text') to exist in the task's data dict. This error means a required config variable is missing from the submitted data. For dotted keys the lookup uses reduce(getitem, keys, data), so a KeyError from any nesting level produces this message.","triggerScenarios":"Importing a task whose data dict lacks the key referenced by the config, e.g. config uses $text but the payload is {'sentence': 'hi'}; or nested config value=\"data.row.text\" where any intermediate key is absent (Task data {'data': {}}).","commonSituations":"Renaming a variable in the label config without updating import payloads; CSV column name mismatch (header 'Text' vs $text); nested JSON imports where an expected intermediate object is absent.","solutions":["Make the task data include every key named by $-references in the labeling config","For dotted keys like data.row.text, provide the full nested object structure","Align import source column/field names with the config variables, or change the config to match the data","Temporarily inspect project.data_types to list the exact required keys"],"exampleFix":"// before\nproject.import_tasks([{'data': {'sentence': 'hello'}}])  # config: <Text value=\"$text\"/>\n// after\nproject.import_tasks([{'data': {'text': 'hello'}}])","handlingStrategy":"validation","validationCode":"def check_keys(payload, data_types):\n    for key in data_types:\n        node = payload\n        for part in key.split('[')[0].split('.'):\n            if not isinstance(node, dict) or part not in node:\n                raise ValueError(f'missing config key: {key}')\n            node = node[part]","typeGuard":"def nested_has(data, dotted):\n    node = data\n    return all(isinstance(node, dict) and part in node and (node := node[part]) is not None for part in dotted.split('.'))","tryCatchPattern":"try:\n    import_tasks(tasks)\nexcept ValidationError as e:\n    m = re.search(r'\"(.+)\" key is expected', str(e.detail[0]))\n    if m:\n        tasks = [add_missing_key(t, m.group(1)) for t in tasks]","preventionTips":["Keep import field names identical to the config's $variables","After editing the label config, re-validate existing payloads","Extract required keys programmatically from project.data_types before import"],"tags":["validation","missing-key","label-config"],"backgroundTag":"missing-required-field","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}