OrchardCMS/OrchardCore · error · InvalidCastException
Cannot convert to DateTimeOffset
Error message
Cannot convert {value} to DateTimeOffset What it means
JsonDynamicValue's explicit operator DateTimeOffset converts the wrapped JSON value via GetValue<DateTimeOffset>() and throws InvalidCastException when the result is null or the JSON token cannot be represented as a DateTimeOffset. The non-nullable operator deliberately fails fast; the nullable sibling returns null instead.
Solutions
- Ensure the JSON value is a parseable DateTimeOffset string (e.g. with offset like 2024-01-01T00:00:00+00:00)
- Use the nullable cast (DateTimeOffset?) and handle null instead of throwing
- Pre-parse with DateTimeOffset.TryParse/DateTimeOffset.Parse on value.ToString() when the format is uncertain
- Null-check the JsonDynamicValue wrapper before casting
Example fix
// before var when = (DateTimeOffset)jsonDynamicValue["Timestamp"]; // after var when = (DateTimeOffset?)jsonDynamicValue["Timestamp"] ?? DateTimeOffset.UtcNow;
Defensive patterns
Strategy: type-guard
Validate before calling
if (jsonDynamicValue is null) throw new InvalidOperationException("null wrapper");
var raw = jsonDynamicValue.ToString();
if (!DateTimeOffset.TryParse(raw, CultureInfo.InvariantCulture, DateTimeStyles.None, out _))
throw new InvalidOperationException($"'{raw}' is not a DateTimeOffset");
var dto = (DateTimeOffset)jsonDynamicValue; Type guard
static bool TryGetDateTimeOffset(JsonDynamicValue v, out DateTimeOffset value)
{
value = default;
if (v is null) return false;
var dto = (DateTimeOffset?)v;
if (dto is null) return false;
value = dto.Value;
return true;
} Try / catch
DateTimeOffset dto;
try
{
dto = (DateTimeOffset)jsonDynamicValue["Timestamp"];
}
catch (InvalidCastException ex)
{
dto = DateTimeOffset.MinValue;
} Prevention
- Always serialize timestamps with an explicit offset (ISO 8601)
- Use (DateTimeOffset?) when the field may be null
- Validate incoming JSON payloads before dynamic reads
- Keep timestamp fields in content types typed as date fields, not text
When it happens
Trigger: Executing `(DateTimeOffset)jsonDynamicValue` where the wrapper or its _jsonValue is null, or the JSON token is a string lacking a timezone-offset-parseable value, a number, boolean, object, or array.
Common situations: Parsing timestamps from JSON payloads where the value is stored as a plain string without offset info or is null; deserializing API/document JSON with dynamic access; timezone-aware fields that were saved as empty strings.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot convert to DateTime
- Cannot convert to Decimal
- Cannot convert to Double
- Cannot convert to Guid
- Cannot convert to
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/c0ef16fef33d240d.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Abstractions/Json/Dynamic/JsonDynamicValue.cs:318
{
return value?._jsonValue?.GetValue<char?>();
}
public static explicit operator DateTime(JsonDynamicValue value)
{
return value?._jsonValue?.GetValue<DateTime>()
?? throw new InvalidCastException($"Cannot convert {value} to DateTime");
}
public static explicit operator DateTime?(JsonDynamicValue value)
{
return value?._jsonValue?.GetValue<DateTime?>();
}
public static explicit operator DateTimeOffset(JsonDynamicValue value)
{
return value?._jsonValue?.GetValue<DateTimeOffset>()
?? throw new InvalidCastException($"Cannot convert {value} to DateTimeOffset");
}
public static explicit operator DateTimeOffset?(JsonDynamicValue value)
{
return value?._jsonValue?.GetValue<DateTimeOffset?>();
}
public static explicit operator decimal(JsonDynamicValue value)
{
return value?._jsonValue?.GetValue<decimal>()
?? throw new InvalidCastException($"Cannot convert {value} to Decimal");
}
public static explicit operator decimal?(JsonDynamicValue value)
{
return value?._jsonValue?.GetValue<decimal?>();
}
View on GitHub (pinned to 4306c0717f)