iOfficeAI/OfficeCLI · error · ArgumentException
Cannot store '{dateText}' as date; Excel does not support da
Error message
Cannot store '{dateText}' as date; Excel does not support dates before 1900-01-01 (serial epoch is 1899-12-30). Use type=string to keep the literal text. What it means
Excel's serial-date epoch is 1899-12-30, and dates earlier than 1900-01-01 are not representable — they round-trip as the epoch and silently mislead the user. When type=date is supplied and the parsed value is before 1900-01-01, this guard rejects it instead of silently clamping, mirroring Set's pre-1900 guard.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs:742
$"Cannot store '{cell.CellValue?.Text}' as number; value must be a finite numeric literal. " +
"Use type=string to keep the literal text.");
}
// CONSISTENCY(cell-type-parity): mirror Set's value auto-detect
// path (ExcelHandler.Set.cs lines 1025-1033) — parse the cell
// value as an ISO date and write it back as an OADate double so
// Excel renders it as a real date instead of a literal string.
if (cellType.Equals("date", StringComparison.OrdinalIgnoreCase))
{
var dateText = cell.CellValue?.Text?.Trim();
// R13-2: accept ISO date-with-time (T separator) as well.
if (!string.IsNullOrEmpty(dateText)
&& TryParseIsoDateFlexible(dateText, out var dt))
{
// Mirrors Set's pre-1900 guard: Excel's serial epoch is
// 1899-12-30; earlier dates round-trip as the epoch and
// mislead the user. Reject instead of silently clamping.
if (dt < new System.DateTime(1900, 1, 1))
throw new ArgumentException(
$"Cannot store '{dateText}' as date; Excel does not support dates before 1900-01-01 " +
$"(serial epoch is 1899-12-30). Use type=string to keep the literal text.");
cell.CellValue = new CellValue(
ExcelDataFormatter.ToExcelSerial(dt, IsWorkbookDate1904()).ToString(System.Globalization.CultureInfo.InvariantCulture));
}
else if (!string.IsNullOrEmpty(dateText))
{
// BUG-FIX(B10): if user said type=date but the value isn't
// parseable, refuse to leave a date-shaped string in a
// numeric-styled cell — that produces invalid OOXML.
throw new ArgumentException(
$"Cannot store '{dateText}' as date; value must be ISO 8601 (yyyy-MM-dd) " +
$"and represent a real calendar day. Use type=string to keep the literal text.");
}
// Apply a default date number format unless the caller
// already supplied one — matches Set's type=date guard.
if (!properties.ContainsKey("numberformat")
&& !properties.ContainsKey("numfmt")View on GitHub (pinned to 1ced45e900)
Solutions
- Store pre-1900 dates as text with type=string, since Excel cannot represent them as serial dates.
- Filter or transform pre-1900 values before the call (e.g. clamp to a sentinel string like 'pre-1900').
- Validate the year >= 1900 when type=date is intended.
Example fix
// before
handler.Add("/Sheet1/A1", "cell", null, new() { ["type"] = "date", ["value"] = "1850-01-01" });
// after
handler.Add("/Sheet1/A1", "cell", null, new() { ["type"] = "string", ["value"] = "1850-01-01" }); Defensive patterns
Strategy: validation
Validate before calling
if (props.GetValueOrDefault("type")?.Equals("date", StringComparison.OrdinalIgnoreCase) == true)
{
if (DateTime.TryParse(props.GetValueOrDefault("value"), out var dt) && dt < new DateTime(1900,1,1))
throw new ArgumentException("date is before Excel's 1900-01-01 epoch");
} Type guard
static bool IsExcelRepresentableDate(string? s) =>
DateTime.TryParse(s, out var dt) && dt >= new DateTime(1900, 1, 1); Try / catch
try { h.Add(parentPath, "cell", pos, props); }
catch (ArgumentException ex) when (ex.Message.Contains("before 1900-01-01"))
{ /* store as type=string instead */ } Prevention
- Filter pre-1900 dates out of date-typed columns.
- Store historical/genealogical dates as text (type=string).
- Validate year >= 1900 before setting type=date.
When it happens
Trigger: Add("/Sheet1/A1","cell",pos,{["type"]="date",["value"]="1899-12-31"}); value="1850-01-01"; value="1066-10-14"; any ISO date that TryParseIsoDateFlexible parses to a DateTime < 1900-01-01.
Common situations: Historical data (birth dates before 1900, genealogical records, archival dates); importing a dataset with mixed-era dates; a default/placeholder sentinel date like 0001-01-01.
Related errors
- Cannot store '{dateText}' as date; value must be ISO 8601 (y
- Unrecognized cell parent path segment '{cellSegments[1]}'. E
- Invalid cell reference: '{cellRef}'
- --prop shift={shiftVal} not valid for add cell. Use 'right'
- Cannot store '{properties.GetValueOrDefault("value") ?? prop
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/f4ab7386bb11e0ca.
Report an issue: GitHub.