stride3d/stride · error · SemanticErrorException

Did not find expected

Error message

Did not find expected <document start>.

What it means

In the explicit-document-start parse state, the parser requires a DocumentStart token ('---') but found some other token. This is raised after directives when the next token is not '---', meaning the document structure is malformed for the state the parser is in.

Solutions

  1. Add the required '---' document-start marker after any %YAML/%TAG directives
  2. Remove the directives entirely if a plain implicit document was intended
  3. Validate the YAML with a linter before loading

Example fix

// before
%YAML 1.1
key: value
// after
%YAML 1.1
---
key: value
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-validate directives are followed by '---'
foreach (var line in File.ReadLines(path))
    if (line.StartsWith("%YAML") || line.StartsWith("%TAG")) requireDocStartAfterDirective = true;

Try / catch

try { stream.Load(reader); } catch (SemanticErrorException ex) { throw new YamlConfigException($"Missing '---' after directives: {ex.Message}", ex); }

Prevention

When it happens

Trigger: Input using %YAML or %TAG directives without a following '---' line, e.g. "%YAML 1.1\nkey: value" (missing '---'), or a second document in a stream missing its '---' separator.

Common situations: Hand-edited YAML configs that add a %YAML directive but forget the '---' marker, concatenating YAML documents without separators.

Related errors


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

Appendix: source

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

                states.Push(ParserState.YAML_PARSE_DOCUMENT_END_STATE);

                state = ParserState.YAML_PARSE_BLOCK_NODE_STATE;

                return new Events.DocumentStart(null, directives, true, GetCurrentToken().Start, GetCurrentToken().End);
            }

            // Parse an explicit document.

            else if (!(GetCurrentToken() is StreamEnd))
            {
                Mark start = GetCurrentToken().Start;
                TagDirectiveCollection directives = new TagDirectiveCollection();
                VersionDirective versionDirective = ProcessDirectives(directives);

                var current = GetCurrentToken();
                if (!(current is DocumentStart))
                {
                    throw new SemanticErrorException(current.Start, current.End, "Did not find expected <document start>.");
                }

                states.Push(ParserState.YAML_PARSE_DOCUMENT_END_STATE);

                state = ParserState.YAML_PARSE_DOCUMENT_CONTENT_STATE;

                Event evt = new Events.DocumentStart(versionDirective, directives, false, start, current.End);
                Skip();
                return evt;
            }

            // Parse the stream end.

            else
            {
                state = ParserState.YAML_PARSE_END_STATE;

                Event evt = new Events.StreamEnd(GetCurrentToken().Start, GetCurrentToken().End);

View on GitHub (pinned to 96fad776d2)