{"record":{"id":"f37c6c4e8366f6ab","repo":"dotnet/wpf","slug":"timing-seekdestinationambiguousduetoslip","errorCode":"Timing_SeekDestinationAmbiguousDueToSlip","errorMessage":"SR.Timing_SeekDestinationAmbiguousDueToSlip (Timing_SeekDestinationAmbiguousDueToSlip)","messagePattern":"SR\\.Timing_SeekDestinationAmbiguousDueToSlip \\(Timing_SeekDestinationAmbiguousDueToSlip\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/Clock.cs","lineNumber":3217,"sourceCode":"                            {\n                                // If the sync child has a specified duration\n                                Duration syncClockDuration = _syncData.SyncClockResolvedDuration;\n\n                                if (syncClockDuration.HasTimeSpan)\n                                {\n                                    _syncData.PreviousSyncClockTime = TimeSpan.FromTicks(ourSyncTimeST.Ticks % syncClockDuration.TimeSpan.Ticks);\n                                    _syncData.PreviousRepeatTime = ourSyncTimeST - _syncData.PreviousSyncClockTime;\n                                }\n                                else if (syncClockDuration == Duration.Forever)\n                                {\n                                    _syncData.PreviousSyncClockTime = ourSyncTimeST;\n                                    _syncData.PreviousRepeatTime = TimeSpan.Zero;\n                                }\n                                else\n                                {\n                                    Debug.Assert(syncClockDuration == Duration.Automatic);\n                                    // If we seek into an Automatic syncChild's duration, we may overseek it, so throw an exception\n                                    throw new InvalidOperationException(SR.Timing_SeekDestinationAmbiguousDueToSlip);\n                                }\n\n                                // This is the heart of the HasSeekOccuredAfterLastTick codepath; we don't adjust our\n                                // time, but note to do so for the succeeding ticks.\n                                _syncData.IsInSyncPeriod = true;\n                            }\n                        }\n                    }\n                    else  // Non-seek, regular case\n                    {\n                        TimeSpan? previousSyncParentTimeSPT = (_syncData.SyncClock == this) ?\n                                                             parentIntervalCollection.FirstNodeTime :\n                                                             _currentTime;\n\n                        if (!previousSyncParentTimeSPT.HasValue\n                            || _syncData.SyncClockDiscontinuousEvent\n                            || previousSyncParentTimeSPT.Value <= _syncData.SyncClockBeginTime)\n                        // Not seeking this tick, different criteria for entering sync period.","sourceCodeStart":3199,"sourceCodeEnd":3235,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Animation/Clock.cs#L3199-L3235","documentation":"During an interactive seek on a ClockGroup with slip behavior, seeking into an Automatic-duration sync child makes the true destination ambiguous — the child's duration is not fixed, so the seek could overseek it. WPF throws InvalidOperationException (Timing_SeekDestinationAmbiguousDueToSlip) rather than guessing a target time.","triggerScenarios":"Calling ClockController.Seek/SeekAlignedToLastTick on a ParallelTimeline/Storyboard with SlipBehavior=\"Slip\" whose sync child has Duration.Automatic, while the clock is inside its sync period (HasSlip configured, e.g. media children).","commonSituations":"Storyboards containing MediaTimeline (video) children with SlipBehavior.Slip; developers seek the storyboard while video is playing and the target time falls inside an automatic-duration segment.","solutions":["Give the slipping child timeline an explicit TimeSpan Duration so seek destinations are unambiguous","Use SlipBehavior=\"Grow\" instead of Slip on the containing ParallelTimeline","Seek individual child clocks rather than the whole group","Wrap the seek in try/catch for InvalidOperationException and retry after the sync period resolves"],"exampleFix":"// before\n<ParallelTimeline SlipBehavior=\"Slip\">\n  <MediaTimeline Source=\"clip.wmv\" BeginTime=\"0:0:2\" />\n</ParallelTimeline>\n// after\n<ParallelTimeline SlipBehavior=\"Slip\">\n  <MediaTimeline Source=\"clip.wmv\" BeginTime=\"0:0:2\" Duration=\"0:0:10\" />\n</ParallelTimeline>","handlingStrategy":"validation","validationCode":"if (groupTimeline.SlipBehavior == SlipBehavior.Slip && childTimeline.Duration == Duration.Automatic)\n    throw new InvalidOperationException(\"Give slipping sync children an explicit Duration before seeking.\");","typeGuard":null,"tryCatchPattern":"try { controller.Seek(target, TimeSeekOrigin.Begin); }\ncatch (InvalidOperationException ex) { /* seek ambiguous: seek child clocks individually or delay */ }","preventionTips":["Assign explicit TimeSpan Durations to slipping (media) child timelines","Avoid seeking a Slip storyboard while a slip child is active; seek the child instead","Prefer SlipBehavior.Grow unless you truly need media-slip semantics"],"tags":["wpf","animation","seek","slip-behavior"],"backgroundTag":"unsupported-operation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}