Skip to content

Apply UnknownDerivedTypeHandling.Fail to tag-based polymorphism#133

Merged
xoofx merged 1 commit into
xoofx:mainfrom
fdcastel:feature/unknown-tag-fail-handling
Mar 29, 2026
Merged

Apply UnknownDerivedTypeHandling.Fail to tag-based polymorphism#133
xoofx merged 1 commit into
xoofx:mainfrom
fdcastel:feature/unknown-tag-fail-handling

Conversation

@fdcastel
Copy link
Copy Markdown
Contributor

Motivation

When using tag-based polymorphism with UnknownDerivedTypeHandling.Fail, unknown property discriminators correctly throw a YamlException. However, unknown YAML tags are silently ignored — the deserializer falls through to the base type without any error.

This inconsistency makes it impossible to detect configuration errors when using tag-based type discrimination (e.g., !http, !ping, !tcp tags). A typo in a tag silently produces a base-type instance instead of failing fast.

Example

[YamlPolymorphic(DiscriminatorStyle = YamlTypeDiscriminatorStyle.Tag)]
[YamlDerivedType(typeof(Dog), Tag = \"!dog\")]
[YamlDerivedType(typeof(Cat), Tag = \"!cat\")]
class Animal { public string Name { get; set; } }
!lizard    # typo — should fail but silently deserializes as Animal
Name: Gecko

Solution

Apply the same Fail/FallBackToBase logic to the tag lookup path, consistent with how property-based discriminators already work:

  1. YamlObjectConverter.ReadPolymorphic() — After the tag lookup fails, check DefaultDerivedType first, then check UnknownDerivedTypeHandling == Fail and throw.
  2. Source generator — Emit the same check after the tag-matching if chain in the generated ReadValue methods.
  3. YamlThrowHelper.ThrowUnknownTypeTag() — New helper for tag-specific error messages (e.g., \"Unknown type tag '!lizard' for 'Animal'\").

Tests

10 new tests covering:

  • Unknown tag with default (Fail) handling via attributes
  • Unknown tag with FallBackToBase via attributes
  • Unknown tag with Fail via options-level DerivedTypeMappings
  • Unknown tag with FallBackToBase via options
  • Attribute-level override takes precedence over options
  • Dictionary values with unknown tags
  • Tag-only entries (no discriminator) with unknown tags
  • Known tags still work correctly

Previously, UnknownDerivedTypeHandling.Fail only applied to property-based
discriminators. Unknown tags in tag-based polymorphism were silently ignored,
falling through to the base type. This made it impossible to detect
configuration errors when using tag-based type discrimination.

This change applies the same Fail/FallBackToBase logic to the tag lookup
path in both the reflection-based converter and the source generator.

A new ThrowUnknownTypeTag helper is added to YamlThrowHelper for
consistent error messages that include the unrecognized tag value.
@xoofx xoofx added the bug label Mar 29, 2026
@xoofx xoofx merged commit c96d42d into xoofx:main Mar 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants