stride3d/stride · error · SemanticErrorException

Found duplicate %TAG directive.

Error message

Found duplicate %TAG directive.

What it means

Each %TAG directive handle (e.g. !e!) may be declared only once per document. If ProcessDirectives sees a TagDirective whose handle is already in the document's tag directive collection, it throws SemanticErrorException at the duplicate's span.

Solutions

  1. Remove the duplicate %TAG directive or rename one of the handles (e.g. use !e2!)
  2. Deduplicate tag directives when merging YAML fragments
  3. In generators, only emit default %TAG directives when the handle isn't already declared

Example fix

// before
%TAG !e! tag:example.com,2000:
%TAG !e! tag:other:
---
// after
%TAG !e! tag:example.com,2000:
%TAG !e2! tag:other:
---
Defensive patterns

Strategy: validation

Validate before calling

var seen = new HashSet<string>();
foreach (var line in File.ReadLines(path))
    if (line.StartsWith("%TAG ") && !seen.Add(line.Split(' ')[1]))
        throw new InvalidDataException($"Duplicate %TAG handle: {line.Split(' ')[1]}");

Try / catch

try { stream.Load(reader); } catch (SemanticErrorException ex) when (ex.Message.Contains("duplicate %TAG")) { /* deduplicate directives and retry */ }

Prevention

When it happens

Trigger: A document declaring the same handle twice, e.g. "%TAG !e! tag:example.com,2000:\n%TAG !e! tag:other:\n---"; or a generator appending default tag directives to input that already defines them.

Common situations: Templated YAML where includes each carry the same %TAG header, concatenating documents' directive blocks.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/63ad5aa2698c9805. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Yaml/Parser.cs:333

                if ((currentVersion = GetCurrentToken() as VersionDirective) != null)
                {
                    if (version != null)
                    {
                        throw new SemanticErrorException(currentVersion.Start, currentVersion.End, "Found duplicate %YAML directive.");
                    }

                    if (currentVersion.Version.Major != Constants.MajorVersion || currentVersion.Version.Minor != Constants.MinorVersion)
                    {
                        throw new SemanticErrorException(currentVersion.Start, currentVersion.End, "Found incompatible YAML document.");
                    }

                    version = currentVersion;
                }
                else if ((tag = GetCurrentToken() as TagDirective) != null)
                {
                    if (tagDirectives.Contains(tag.Handle))
                    {
                        throw new SemanticErrorException(tag.Start, tag.End, "Found duplicate %TAG directive.");
                    }
                    tagDirectives.Add(tag);
                    if (tags != null)
                    {
                        tags.Add(tag);
                    }
                }
                else
                {
                    break;
                }

                Skip();
            }

            if (tags != null)
            {
                AddDefaultTagDirectives(tags);

View on GitHub (pinned to 96fad776d2)