stride3d/stride · error · NotImplementedException
Unknown node type
Error message
Unknown node type
What it means
ErrorRecoverySerializer scans YAML parsing events to recover type/assembly tags from errored nodes; when the first node is neither a Mapping, Sequence nor Scalar it throws NotImplementedException('Unknown node type'). The recovery path simply has no handling for that node kind.
Solutions
- Fix the YAML source so the root node is a mapping, sequence, or scalar (remove root-level anchors/aliases)
- Re-export or regenerate the asset from Stride instead of repairing the YAML manually
- Check YamlDotNet/Stride version compatibility between the tool that wrote the asset and the reader
- Extend ErrorRecoverySerializer to handle the missing node kind if you own the pipeline
Example fix
# before (root alias, unsupported) &base object # after (plain mapping root) root: Key: value
Defensive patterns
Strategy: validation
Validate before calling
using var parser = new YamlMappingNode(...); // ensure root is a mapping/sequence/scalar
if (doc.RootNode is YamlAliasNode) throw new InvalidOperationException("Root alias unsupported"); Type guard
bool HasSupportedRoot(YamlDocument doc) =>
doc.RootNode is YamlMappingNode or YamlSequenceNode or YamlScalarNode; Try / catch
try { return errorRecoverySerializer.ReadYaml(parser, expectedType); }
catch (NotImplementedException ex) { logger.Error(ex, "Unsupported YAML root node during error recovery"); return null; } Prevention
- Keep document roots as plain mappings in asset YAML
- Avoid anchors/aliases at the root of asset files
- Keep Stride/YamlDotNet versions aligned between writer and reader
When it happens
Trigger: ReadYaml encountering a YAML document whose first event is an anchor/alias or other exotic node type (not mapping, sequence, or scalar) during error recovery of a malformed asset.
Common situations: Corrupted or hand-edited Stride asset YAML containing aliases/anchors at the document root; a parser producing unexpected event streams after partial reads; assets saved by a newer Stride/YamlDotNet emitting node kinds the recovery code predates.
Related errors
- Multiple identifiable objects with the same id
- Unable to decode asset part reference
- Unable to deserialize reference
- Unable to find class from tag
- Unable to find property
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/651f6418850b552e.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets/Yaml/ErrorRecoverySerializer.cs:90
tag = firstNode.Tag;
// Temporarily recreate the node without its tag, so that we can try deserializing as many members as possible still
// TODO: Replace this with switch pattern matching (C# 7.0)
if (firstNode is MappingStart mappingStart)
{
memoryParser.ParsingEvents[startPosition] = new MappingStart(mappingStart.Anchor, null, mappingStart.IsImplicit, mappingStart.Style, mappingStart.Start, mappingStart.End);
}
else if (firstNode is SequenceStart sequenceStart)
{
memoryParser.ParsingEvents[startPosition] = new SequenceStart(sequenceStart.Anchor, null, sequenceStart.IsImplicit, sequenceStart.Style, sequenceStart.Start, sequenceStart.End);
}
else if (firstNode is Scalar scalar)
{
memoryParser.ParsingEvents[startPosition] = new Scalar(scalar.Anchor, null, scalar.Value, scalar.Style, scalar.IsPlainImplicit, scalar.IsQuotedImplicit, scalar.Start, scalar.End);
}
else
{
throw new NotImplementedException("Unknown node type");
}
}
string? typeName = null;
string? assemblyName = null;
if (tag != null)
{
var tagAsType = tag.StartsWith('!') ? tag[1..] : tag;
objectContext.SerializerContext.ParseType(tagAsType, out typeName, out assemblyName);
}
var log = objectContext.SerializerContext.Logger;
log?.Warning($"Could not deserialize object of type '{typeName ?? tag}'; replacing it with an object implementing {nameof(IUnloadable)}", ex);
var unloadableObject = UnloadableObjectInstantiator.CreateUnloadableObject(type, typeName, assemblyName, ex.Message, parsingEvents);
objectContext.Instance = unloadableObject;
objectContext.Descriptor = objectContext.SerializerContext.FindTypeDescriptor(unloadableObject.GetType());
View on GitHub (pinned to 96fad776d2)