dotnet/wpf · error · FormatException

is not a valid value for .

Error message

{valueSpan} is not a valid value for {nameof(TimeSpan)}.

What it means

DurationConverter.ParseTimeSpan wraps a FormatException from TimeSpan.Parse and rethrows it with a message naming the offending valueSpan, preserving the inner exception. It fires during ConvertFrom when a string (typically from XAML) cannot be parsed as a TimeSpan for a Duration. The wrapper exists so the error message states which value failed.

Solutions

  1. Correct the duration string to a parseable TimeSpan format (e.g. "0:0:5" or "00:00:05")
  2. Inspect the inner FormatException for the exact parse failure
  3. Use TimeSpan.TryParse to validate user-provided duration strings before assignment

Example fix

// before
<Storyboard Duration="five seconds" />
// after
<Storyboard Duration="0:0:5" />
Defensive patterns

Strategy: try-catch

Validate before calling

if (TimeSpan.TryParse(value, CultureInfo.InvariantCulture, out _)) { /* safe */ }

Type guard

bool IsValidDurationString(string s) => TimeSpan.TryParse(s, CultureInfo.InvariantCulture, out _);

Try / catch

try { var d = (Duration)converter.ConvertFrom(null, culture, text); } catch (FormatException e) { log(e.InnerException ?? e); useDefaultDuration(); }

Prevention

When it happens

Trigger: Calling DurationConverter.ConvertFrom (or the TypeConverter pipeline during XAML/BAML loading) with a string that TimeSpan.Parse rejects, e.g. "abc", "1:2", or an empty string.

Common situations: Typos in XAML animation durations; culture mismatch where the expected ':'-separated format differs; localized resource strings containing an invalid duration; binding a string property to a Duration target without conversion.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/eed3c0dcba9e47bc. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/DurationConverter.cs:80

        }

        /// <summary>
        /// Facilities parsing from <paramref name="valueSpan"/> to <see cref="TimeSpan"/> and initializes new <see cref="Duration"/> instance.
        /// </summary>
        /// <param name="valueSpan">The string to convert from.</param>
        /// <param name="cultureInfo">The culture specifier to use.</param>
        /// <returns>A newly initialized <see cref="Duration"/> instance from the <paramref name="valueSpan"/> string.</returns>
        /// <remarks>This function is decoupled from the <see cref="ConvertFrom(ITypeDescriptorContext, CultureInfo, object)"/> for performance reasons.</remarks>
        /// <exception cref="FormatException">Thrown when parsing of <paramref name="valueSpan"/> to <see cref="TimeSpan"/> instance fails.</exception>
        private static Duration ParseTimeSpan(ReadOnlySpan<char> valueSpan, CultureInfo cultureInfo)
        {
            try
            {
                return new Duration(TimeSpan.Parse(valueSpan, cultureInfo));
            }
            catch (FormatException e)
            {
                throw new FormatException($"{valueSpan} is not a valid value for {nameof(TimeSpan)}.", e);
            }
        }

        /// <summary>
        /// Converts a <paramref name="value"/> of <see cref="Duration"/> to its <see cref="string"/> representation.
        /// </summary>
        /// <param name="context">Context information used for conversion.</param>
        /// <param name="cultureInfo">The culture specifier to use, currently ignored during conversion.</param>
        /// <param name="value">Duration value to convert from.</param>
        /// <param name="destinationType">Type being evaluated for conversion.</param>
        /// <returns>A <see cref="string"/> representing the <see cref="Duration"/> specified by <paramref name="value"/>.</returns>
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cultureInfo, object value, Type destinationType)
        {
            ArgumentNullException.ThrowIfNull(destinationType);

            // Check that we actually support the conversion, NULL value results in string.Empty, others throw
            if (value is not Duration duration || (destinationType != typeof(InstanceDescriptor) && destinationType != typeof(string)))
                return base.ConvertTo(context, cultureInfo, value, destinationType);

View on GitHub (pinned to 81131a70a4)