dotnet/wpf · error · ArgumentException
SR.Storyboard_UnrecognizedHandoffBehavior
Error message
SR.Storyboard_UnrecognizedHandoffBehavior
What it means
Thrown by Storyboard's public Begin overload when the handoffBehavior argument is not a defined member of the HandoffBehavior enum. The library validates enum arguments with HandoffBehaviorEnum.IsDefined and rejects unknown values via ArgumentException before creating clocks.
Solutions
- Pass one of the defined values: HandoffBehavior.SnapshotAndReplace, Compose, SnapshotAndReplace, or SnapshotAndReplace's siblings (SnapshotAndReplace, Compose are the valid members).
- If the value comes from external input, validate it with Enum.IsDefined(typeof(HandoffBehavior), value) before passing it.
- Fix serialization/deserialization of the enum (store as string, or clamp/validate on read).
Example fix
// before var hb = (HandoffBehavior)storedInt; // may be out of range storyboard.Begin(this, true, hb); // after var hb = Enum.IsDefined(typeof(HandoffBehavior), storedInt) ? (HandoffBehavior)storedInt : HandoffBehavior.SnapshotAndReplace; storyboard.Begin(this, true, hb);
Defensive patterns
Strategy: type-guard
Validate before calling
bool valid = Enum.IsDefined(typeof(HandoffBehavior), handoffBehavior); if (!valid) handoffBehavior = HandoffBehavior.SnapshotAndReplace;
Type guard
bool IsValidHandoff(HandoffBehavior hb) => hb is HandoffBehavior.SnapshotAndReplace or HandoffBehavior.Compose;
Try / catch
try { sb.Begin(this, true, hb); }
catch (ArgumentException ex) when (ex.ParamName == null || ex.Message.Contains("Handoff")) { sb.Begin(this, true, HandoffBehavior.SnapshotAndReplace); } Prevention
- Never cast raw ints to HandoffBehavior without Enum.IsDefined
- Store enums as strings when persisting
- Use the named enum members instead of casts
When it happens
Trigger: Calling Storyboard.Begin/Begin(containingObject, isControllable, handoffBehavior, ...) with a HandoffBehavior value outside 0..3, e.g. a cast of an uninitialized or bogus integer like (HandoffBehavior)99.
Common situations: Persisting the enum to config/database as a raw int and reading back a stale or out-of-range value; interop code computing the enum; .NET version differences introducing/garbling values.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- SR.Animation_UnrecognizedHandoffBehavior
- SR.Animation_UnrecognizedHandoffBehavior
- Animation_UnrecognizedHandoffBehavior
- Enum_Invalid
- InvalidEnumArgumentException(value, (int) value…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/69e0bfc315d95789.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Media/Animation/Storyboard.cs:1215
INameScope nameScope = null;
HandoffBehavior handoffBehavior = HandoffBehavior.SnapshotAndReplace;
bool isControllable = true;
Int64 layer = Storyboard.Layers.Code;
BeginCommon(containingObject, nameScope, handoffBehavior, isControllable, layer);
}
/// <summary>
/// Begins all animations underneath this storyboard, clock tree starts at the given containing object.
/// </summary>
internal void BeginCommon( DependencyObject containingObject, INameScope nameScope,
HandoffBehavior handoffBehavior, bool isControllable, Int64 layer)
{
ArgumentNullException.ThrowIfNull(containingObject);
if (!HandoffBehaviorEnum.IsDefined(handoffBehavior))
{
throw new ArgumentException(SR.Storyboard_UnrecognizedHandoffBehavior);
}
if (BeginTime == null)
{
// a null BeginTime means to not allocate or start the clock
return;
}
// It's not possible to begin when there is no TimeManager. This condition
// is known to occur during app shutdown. Since an app being shut down
// won't care about its Storyboards, we silently exit.
// If we don't exit here, we'll need to catch and handle the "no time
// manager" exception implemented for bug #1247862
if( MediaContext.CurrentMediaContext.TimeManager == null )
{
return;
}
View on GitHub (pinned to 81131a70a4)