iOfficeAI/OfficeCLI · error · ArgumentException
Literal braces '{...}' around a formula create an Excel-reje
Error message
Literal braces '{...}' around a formula create an Excel-rejected file. Use --prop arrayformula=... (without braces) to declare a CSE array formula. What it means
A CSE array formula must be declared with the `arrayformula=` property, which emits the correct OOXML (<f t="array">). Wrapping the formula= text in literal braces (e.g. {=SUM(...)}) writes `<f>{=...}</f>`, which Excel rejects on open. This guard detects a formula that starts with '{' and ends with '}' after trimming the leading '=' and rejects it, directing the user to arrayformula=.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs:619
}
else if (!double.TryParse(safeValue, out var dbl) || !double.IsFinite(dbl))
cell.DataType = new EnumValue<CellValues>(CellValues.String);
else
// R-fuzz2-1: TryParse accepts spellings Excel's <v> parser
// does not ("+5", "1,234", padded). Store the canonical
// form; literal digits are preserved when already canonical.
cell.CellValue = new CellValue(NormalizeNumericCellText(safeValue, dbl));
}
}
if (properties.TryGetValue("formula", out var formula))
{
// Strip a leading '=' (formula-bar copy) and reject
// literal `{...}` array-formula wrapping — users must use
// the dedicated `arrayformula=` prop for that, since
// `<x:f>{=...}</x:f>` causes Excel to reject the file.
var fTrim = formula.TrimStart('=').Trim();
if (fTrim.StartsWith("{") && fTrim.EndsWith("}"))
throw new ArgumentException("Literal braces '{...}' around a formula create an Excel-rejected file. Use --prop arrayformula=... (without braces) to declare a CSE array formula.");
RejectCrossWorkbookFormula(fTrim);
ValidateFormulaCellRefs(fTrim);
var addCellFormula = new CellFormula(Core.PivotTableHelper.SanitizeXmlText(Core.ModernFunctionQualifier.Qualify(Core.ModernFunctionQualifier.AutoQuoteSheetRefs(fTrim))));
// Dynamic-array functions (SORT/FILTER/UNIQUE/SEQUENCE/XLOOKUP/LET/etc.)
// carry t="array" ref="<cellRef>" on the cell-level CellFormula PLUS a
// cm cell-metadata index into an XLDAPR record (EnsureDynamicArrayMetadata)
// — t="array" alone is a legacy CSE array locked to the anchor; the
// XLDAPR metadata is what makes Excel 365 spill. The anchor reference is
// the single cell being written; Excel recomputes the spill extent and
// fills adjacent cells at runtime.
if (Core.ModernFunctionQualifier.IsDynamicArrayFormula(fTrim) && cell.CellReference?.Value != null)
{
addCellFormula.FormulaType = CellFormulaValues.Array;
addCellFormula.Reference = cell.CellReference.Value;
EnsureDynamicArrayMetadata(cell);
}
// CONSISTENCY(value-child-uniqueness): clear any stale <is> so the
// cell never carries both a formula and an inline string (invalidView on GitHub (pinned to 1ced45e900)
Solutions
- Use the arrayformula= property without braces: arrayformula="B1:B3*C1:C3" (with or without leading '=').
- If it is a normal (non-array) formula, remove the braces entirely and use formula=.
- For a single-cell dynamic-array formula (SORT/FILTER/UNIQUE/etc.), you can also use formula= without braces — dynamic arrays do not need CSE wrapping.
Example fix
// before
handler.Add("/Sheet1/A1", "cell", null, new() { ["formula"] = "{=B1:B3*C1:C3}" });
// after
handler.Add("/Sheet1/A1", "cell", null, new() { ["arrayformula"] = "B1:B3*C1:C3" }); Defensive patterns
Strategy: validation
Validate before calling
if (props.TryGetValue("formula", out var f))
{
var ft = f.TrimStart('=').Trim();
if (ft.StartsWith("{") && ft.EndsWith("}"))
{
props.Remove("formula");
props["arrayformula"] = ft.Trim('{', '}');
}
}
h.Add(parentPath, "cell", pos, props); Type guard
static bool IsBraceWrappedFormula(string f)
{ var t = f.TrimStart('=').Trim(); return t.StartsWith("{") && t.EndsWith("}"); } Try / catch
try { h.Add(parentPath, "cell", pos, props); }
catch (ArgumentException ex) when (ex.Message.Contains("Literal braces"))
{ /* move text to arrayformula= without braces and retry */ } Prevention
- Always use the arrayformula= property for CSE array formulas.
- Strip braces copied from the Excel formula bar before passing as formula=.
- Dynamic-array functions (SORT/FILTER/etc.) work via plain formula= without braces.
When it happens
Trigger: Add("/Sheet1/A1","cell",pos,{["formula"]="{=B1:B3*C1:C3}"}); formula="{SUM(A1:A3)}"; any formula= value that, after TrimStart('=').Trim(), is brace-wrapped.
Common situations: Copying a formula straight from the Excel formula bar where array formulas display with braces; following a tutorial that shows the braced form; forgetting that arrayformula= is the dedicated property.
Related errors
- Invalid cell reference: '{cellRef}'
- arrayformula=true requires a formula: pass the text directly
- Unrecognized cell parent path segment '{cellSegments[1]}'. E
- --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/9b06c81d1081313c.
Report an issue: GitHub.