iOfficeAI/OfficeCLI · error · ArgumentException
number format has unbalanced square brackets: '{formatCode}'
Error message
number format has unbalanced square brackets: '{formatCode}'. Bracket codes ([Red], [>=100], [h]) must be closed; writing an unbalanced bracket makes Excel refuse to open the file. What it means
Thrown when a custom Excel number format has unbalanced square brackets. Bracket codes ([Red], [>=100], [h]) must be closed; the writer counts brackets outside quoted literals (and treats escaped \[ as a literal), then rejects the format if the depth is non-zero. Real Excel refuses the whole file (0x800A03EC) on an unbalanced bracket, so this guard blocks it at write time.
Source
Thrown at src/officecli/Core/ExcelStyleManager.cs:742
// Unbalanced [brackets] (e.g. formatCode="[") pass schema validation
// but real Excel refuses the whole file (0x800A03EC). Count outside
// quoted literals; escaped \[ is a literal char.
int nfBracketDepth = 0;
bool nfBrQuote = false;
for (int i = 0; i < formatCode.Length; i++)
{
var c = formatCode[i];
if (c == '"') nfBrQuote = !nfBrQuote;
else if (!nfBrQuote && c == '\\') i++;
else if (!nfBrQuote && c == '[') nfBracketDepth++;
else if (!nfBrQuote && c == ']')
{
nfBracketDepth--;
if (nfBracketDepth < 0) break;
}
}
if (nfBracketDepth != 0)
throw new ArgumentException(
$"number format has unbalanced square brackets: '{formatCode}'. Bracket codes ([Red], [>=100], [h]) must be closed; writing an unbalanced bracket makes Excel refuse to open the file.");
// Unquoted letters outside Excel's token alphabet (date/time/era/
// General letters) make real Excel refuse the whole file
// (0x800A03EC) while schema validation stays green — e.g. a typoed
// numfmt=invalid_fmt instead of "invalid_fmt"0. Excel's grammar is
// quirky enough (abc opens, xyz does not) that a hard reject risks
// false positives on locale codes, so warn instead of block.
{
const string TokenLetters = "abcdeghlmnprsty";
bool warnQuote = false;
int warnBracket = 0;
char? suspect = null;
for (int i = 0; i < formatCode.Length && suspect == null; i++)
{
var c = formatCode[i];
if (c == '"') { warnQuote = !warnQuote; continue; }
if (warnQuote) continue;View on GitHub (pinned to 1ced45e900)
Solutions
- Balance the brackets: ensure every '[' has a matching ']' in the format code.
- If you need a literal bracket in output, escape it as \[ or \] or put it inside a quoted literal "[".
- Validate the format with the project's number-format checker before writing.
Example fix
// before style.NumberFormat = "[Red0.00"; // missing ] // after style.NumberFormat = "[Red]0.00";
Defensive patterns
Strategy: validation
Validate before calling
static bool BracketsBalanced(string fmt)
{
int depth = 0; bool inQuote = false;
for (int i = 0; i < fmt.Length; i++)
{
var c = fmt[i];
if (c == '"') inQuote = !inQuote;
else if (!inQuote && c == '\\') i++;
else if (!inQuote && c == '[') depth++;
else if (!inQuote && c == ']') { depth--; if (depth < 0) return false; }
}
return depth == 0;
} Try / catch
try { ApplyNumberFormat(fmt); }
catch (ArgumentException ex) when (ex.Message.Contains("unbalanced square brackets"))
{ /* fix or escape brackets */ } Prevention
- Escape literal brackets as \[ / \] or quote them.
- Pre-validate bracket balance before writing the format.
When it happens
Trigger: Setting numberFormat to a string with an unclosed bracket such as "[Red" or "[>=100" or a stray "["; the validator counts '[' and ']' ignoring those inside double quotes or after a backslash and throws when depth != 0.
Common situations: Hand-building a format string with string interpolation that drops the closing ']'; a typoed predicate like [>100 instead of [>100]; copy-paste truncating the format.
Related errors
- number format is {formatCode.Length} chars; Excel's limit is
- Property 'sqref' (or 'range'/'ref') is required for validati
- invalid_value
- unsupported_type
- Invalid font size: '{szVal}'. Excel font size must be <= 409
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/2e12fb62a7578460.
Report an issue: GitHub.