JamesNK/Newtonsoft.Json · error · JsonSerializationException

Unexpected value when converting date. Expected DateTime or

Error message

Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.

What it means

Thrown by IsoDateTimeConverter.WriteJson when the value being serialized is neither a DateTime nor a DateTimeOffset. The converter formats dates to ISO strings; any other runtime type (and the DateTimeOffset branch being compiled out on platforms without HAVE_DATE_TIME_OFFSET) falls through to this JsonSerializationException.

Source

Thrown at Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs:107

                }

                text = dateTime.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
            }
#if HAVE_DATE_TIME_OFFSET
            else if (value is DateTimeOffset dateTimeOffset)
            {
                if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
                    || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
                {
                    dateTimeOffset = dateTimeOffset.ToUniversalTime();
                }

                text = dateTimeOffset.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
            }
#endif
            else
            {
                throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value)!));
            }

            writer.WriteValue(text);
        }

        /// <summary>
        /// Reads the JSON representation of the object.
        /// </summary>
        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="existingValue">The existing value of object being read.</param>
        /// <param name="serializer">The calling serializer.</param>
        /// <returns>The object value.</returns>
        public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
        {
            bool nullable = ReflectionUtils.IsNullableType(objectType);
            if (reader.TokenType == JsonToken.Null)
            {

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Ensure the value is a DateTime or DateTimeOffset before it reaches IsoDateTimeConverter.
  2. For DateOnly/TimeOnly, convert to DateTime before serializing or use a dedicated converter.
  3. Remove the [JsonConverter(typeof(IsoDateTimeConverter))] attribute from properties that are no longer dates.
  4. If serializing a custom date type, map it to DateTime first or implement a purpose-built converter.

Example fix

// before: DateOnly is not DateTime/DateTimeOffset
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateOnly BirthDate { get; set; }

// after: use a DateOnly-aware approach
[JsonConverter(typeof(DateOnlyJsonConverter))]
public DateOnly BirthDate { get; set; }
Defensive patterns

Strategy: type-guard

Validate before calling

object value = GetValue();
if (value != null && !(value is DateTime) && !(value is DateTimeOffset))
    throw new InvalidOperationException($"IsoDateTimeConverter cannot serialize {value.GetType()}");

Type guard

static bool IsDateType(object v) =>
    v is DateTime || v is DateTimeOffset;

Try / catch

try { conv.WriteJson(writer, value, serializer); }
catch (JsonSerializationException ex) when (ex.Message.Contains("Expected DateTime or DateTimeOffset"))
{
    throw new InvalidOperationException($"IsoDateTimeConverter got {value?.GetType()}", ex);
}

Prevention

When it happens

Trigger: Applying IsoDateTimeConverter to a property/type whose runtime value is not DateTime or DateTimeOffset (e.g. a DateOnly, TimeSpan, string, or custom date struct). Also on platforms where DateTimeOffset support is compiled out, passing a DateTimeOffset triggers it.

Common situations: Using IsoDateTimeConverter with .NET 6+ DateOnly/TimeOnly which are not handled. A refactor changed a property from DateTime to string but left the converter attribute. A polymorphic object whose runtime type is unexpected at serialization time.

Related errors


AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07). Data as JSON: /api/errors/010f19f0971939a6. Report an issue: GitHub.