HumanSignal/label-studio · error · ValidationError

toName="{toName}" not found in names: {sorted(names)}

Error message

toName="{toName}" not found in names: {sorted(names)}

What it means

Every toName="..." reference in the label config must point to a name declared by another tag. validate_label_config splits comma-separated toName lists and raises this ValidationError listing the missing name and the sorted set of known names when a reference is dangling.

Source

Thrown at label_studio/core/label_config.py:135

        # we pick the first failed schema and show only its error message
        error_message = exc.context[0].message if len(exc.context) else exc.message
        error_message = 'Validation failed on {}: {}'.format(
            '/'.join(map(str, exc.path)), error_message.replace('@', '')
        )
        raise ValidationError(error_message)

    # unique names in config # FIXME: 'name =' (with spaces) won't work
    all_names = re.findall(r'(?:^|[^\w])name="([^"]*)"', cleaned_config_string)
    if len(set(all_names)) != len(all_names):
        raise ValidationError('Label config contains non-unique names: ' + ', '.join(all_names))

    # toName points to existent name
    names = set(all_names)
    toNames = re.findall(r'toName="([^"]*)"', cleaned_config_string)
    for toName_ in toNames:
        for toName in toName_.split(','):
            if toName not in names:
                raise ValidationError(f'toName="{toName}" not found in names: {sorted(names)}')

    # Tag attribute validation (e.g. Video playback speed) via SDK
    try:
        li = LabelInterface(config_string)
        if hasattr(li, '_tag_attribute_validation'):
            li._tag_attribute_validation()
    except LabelStudioValidationErrorSentryIgnored as exc:
        raise ValidationError(str(exc))


def extract_data_types(label_config):
    # load config
    xml = parse_config_to_xml(label_config)
    if xml is None:
        raise etree.ParseError('Project config is empty or incorrect')

    # take all tags with values attribute and fit them to tag types
    data_type = {}

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Add a tag with the referenced name, or fix toName to match an existing tag name exactly (case-sensitive).
  2. Cross-check each toName value against the sorted names list included in the error message.
  3. After renaming a tag, update every toName that referenced the old name.
  4. If a tag controls multiple targets, list them comma-separated in toName, e.g. toName="text,audio".

Example fix

<!-- before: toName references nonexistent name 'txet' -->
<Text name="text" value="$doc"/>
<Choices name="sentiment" toName="txet">...</Choices>
<!-- after -->
<Text name="text" value="$doc"/>
<Choices name="sentiment" toName="text">...</Choices>
Defensive patterns

Strategy: validation

Validate before calling

import re
def to_names_resolve(config: str) -> bool:
    names = set(re.findall(r'(?:^|[^\w])name="([^"]*)"', config))
    return all(t in names for to in re.findall(r'toName="([^"]*)"', config) for t in to.split(','))

Try / catch

try:
    validate_label_config(config)
except ValidationError as e:
    if 'not found in names' in str(e):
        return Response({'error': str(e), 'hint': 'toName must reference an existing tag name'}, status=400)
    raise

Prevention

When it happens

Trigger: Saving a config where a tag's toName attribute references a name that no tag declares — e.g. <Choices toName="text"> with no tag named text; also triggered by a typo in toName, or after renaming/deleting a source tag.

Common situations: Deleting or renaming a tag while leaving its consumers' toName unchanged; typos (case-sensitive mismatch); forgetting the controlling tag entirely in minimal configs.

Related errors


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