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

  1. Pass one of the defined values: HandoffBehavior.SnapshotAndReplace, Compose, SnapshotAndReplace, or SnapshotAndReplace's siblings (SnapshotAndReplace, Compose are the valid members).
  2. If the value comes from external input, validate it with Enum.IsDefined(typeof(HandoffBehavior), value) before passing it.
  3. 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

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


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)