stride3d/stride · error · YamlException

Unable to find class from tag

Error message

Unable to find class from tag [{0}]

What it means

PropertyKeyYamlSerializer.ConvertFrom resolves a scalar of the form 'ClassName.PropertyName' to a static field value. It first resolves the class part via the YAML tag system; if no registered tag maps to that class it throws YamlException 'Unable to find class from tag [{0}]'.

Solutions

  1. Verify the class name prefix matches an existing, registered class (tags are case-sensitive)
  2. Ensure the assembly containing the class is loaded and its types are registered with the YamlSerializer
  3. Re-export/regenerate the YAML against the current schema after renames
  4. Catch YamlException and fall back to a default value or skip the property

Example fix

// before
key: MyoldNamespace.OldClass.MyProperty
// after
key: MyNamespace.RenamedClass.MyProperty
Defensive patterns

Strategy: try-catch

Validate before calling

var cls = scalar.Substring(0, scalar.LastIndexOf('.'));
bool registered = typeRegistry.Tags.Contains("!" + cls);

Try / catch

try { key = serializer.ConvertFrom(ctx, scalar); }
catch (YamlException ex) { /* log missing tag, use default key */ }

Prevention

When it happens

Trigger: A YAML document references a property key whose class prefix is not registered with the serializer's tag system — misspelled class name, missing using/assembly, renamed class, or YAML written against a different (older/newer) schema version.

Common situations: Renaming a class after assets were serialized; loading assets from another project/version where the tag isn't registered; typos in fully-qualified key names in hand-authored YAML.

Related errors


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

Appendix: source

Thrown at sources/core/Stride.Core.Design/Yaml/PropertyKeyYamlSerializer.cs:43

        {
            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(PropertyKey<>))
                return true;
        }

        return false;
    }

    public override object? ConvertFrom(ref ObjectContext objectContext, Scalar fromScalar)
    {
        var lastDot = fromScalar.Value.LastIndexOf('.');
        if (lastDot == -1)
            return null;

        var className = fromScalar.Value[..lastDot];
        var containingClass = objectContext.SerializerContext.TypeFromTag("!" + className, out _); // Readd initial '!'
        if (containingClass == null)
        {
            throw new YamlException(fromScalar.Start, fromScalar.End, "Unable to find class from tag [{0}]".ToFormat(className));
        }

        var propertyName = fromScalar.Value[(lastDot + 1)..];
        var propertyField = containingClass.GetField(propertyName, BindingFlags.Public | BindingFlags.Static);
        if (propertyField == null)
        {
            throw new YamlException(fromScalar.Start, fromScalar.End, "Unable to find property [{0}] in class [{1}]".ToFormat(propertyName, containingClass.Name));
        }

        return propertyField.GetValue(null);
    }

    protected override void WriteScalar(ref ObjectContext objectContext, ScalarEventInfo scalar)
    {
        // TODO: if ParameterKey is written to an object, It will not serialized a tag
        scalar.Tag = null;
        scalar.IsPlainImplicit = true;
        base.WriteScalar(ref objectContext, scalar);

View on GitHub (pinned to 96fad776d2)