iOfficeAI/OfficeCLI · error · ArgumentException
Invalid 'secondaryAxis' value: '{value}'. Valid forms: index
Error message
Invalid 'secondaryAxis' value: '{value}'. Valid forms: index ('2'), comma index list ('2,3'), 'true', 'false'/'none', seriesN alias ('series2'), or a chart-type name on a combo chart ('line'). What it means
Thrown when 'secondaryAxis' does not match any accepted form after all parses fail: it is not 'true', not 'false'/'none'/blank, not a comma list of positive integer indices, not a 'seriesN' alias list, and not a chart-type name present on a combo chart (SeriesIndicesForChartType returned empty). This is the R47 guard that replaced the old silent no-op behavior.
Source
Thrown at src/officecli/Core/Chart/ChartHelper.Setter.cs:1725
var trimmed = s.Trim();
if (int.TryParse(trimmed, out var v)) return v;
var m = System.Text.RegularExpressions.Regex.Match(
trimmed, @"^series(\d+)$",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
return m.Success && int.TryParse(m.Groups[1].Value, out var sv) ? sv : -1;
})
.Where(v => v > 0).ToHashSet();
// Type-name form, e.g. "line" on a combo chart — route every
// series whose parent CT_*Chart element matches that type to
// the secondary axis. Without this, "line" parsed to an empty
// index set and silently no-op'd, leaving the lineChart bound
// to the primary axId (the R26 combo bug).
if (secondaryIndices.Count == 0)
secondaryIndices = SeriesIndicesForChartType(plotArea2, value);
// R47: still empty → value was not a valid index, type name,
// or seriesN alias. Throw instead of silent no-op.
if (secondaryIndices.Count == 0)
throw new ArgumentException(
$"Invalid 'secondaryAxis' value: '{value}'. Valid forms: " +
"index ('2'), comma index list ('2,3'), 'true', 'false'/'none', " +
"seriesN alias ('series2'), or a chart-type name on a combo chart ('line').");
}
ApplySecondaryAxis(plotArea2, secondaryIndices);
break;
}
case "plotarea.x" or "plotarea.y" or "plotarea.w" or "plotarea.h":
{
if (!double.TryParse(value, System.Globalization.NumberStyles.Float,
System.Globalization.CultureInfo.InvariantCulture, out var layoutVal)
|| !double.IsFinite(layoutVal))
{ unsupported.Add(key); break; }
var plotArea3 = chart.GetFirstChild<C.PlotArea>();
if (plotArea3 == null) { unsupported.Add(key); break; }
SetManualLayoutProperty(plotArea3, key.Split('.')[1].ToLowerInvariant(), layoutVal, isPlotArea: true);
break;View on GitHub (pinned to 1ced45e900)
Solutions
- Use a 1-based index or comma list ('2', '2,3'), 'series2' alias, 'true', 'false'/'none', or a chart-type name that exists on the combo chart.
- For zero-based UIs, convert: send (uiIndex + 1).
- Verify the type-name against the chart's actual CT_*Chart elements before sending.
Example fix
// before
SetChartProperties(part, new() { ["secondaryAxis"] = "0" });
// after
SetChartProperties(part, new() { ["secondaryAxis"] = (uiIndex + 1).ToString() }); Defensive patterns
Strategy: validation
Validate before calling
static readonly Regex SeriesAlias = new(@"^series(\d+)$", RegexOptions.IgnoreCase);
static bool IsValidSecondaryAxis(string v)
{
if (string.IsNullOrWhiteSpace(v)) return true; // no-op
if (v.Equals("true", StringComparison.OrdinalIgnoreCase)) return true;
if (v.Equals("false", StringComparison.OrdinalIgnoreCase)) return true;
if (v.Equals("none", StringComparison.OrdinalIgnoreCase)) return true;
foreach (var part in v.Split(','))
{
var t = part.Trim();
if (int.TryParse(t, out var n) && n > 0) continue;
if (SeriesAlias.IsMatch(t)) continue;
return false; // type-name form must be validated against the chart's series
}
return true;
} Type guard
static bool IsIndexOrAlias(string v) =>
(int.TryParse(v, out var n) && n > 0)
|| SeriesAlias.IsMatch(v); Try / catch
try { SetChartProperties(part, props); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Invalid 'secondaryAxis'"))
{ /* surface accepted forms to the user; indices are 1-based */ } Prevention
- Indices are 1-based — convert zero-based UIs by adding 1.
- For type-name form, ensure the chart actually has a series of that type (combo chart).
- Whitelist 'true'/'false'/'none' and seriesN aliases explicitly.
When it happens
Trigger: SetChartProperties with { ["secondaryAxis"] = "all" }, "second", "0" (zero is filtered out), or a type name like 'area' on a chart that has no area series.
Common situations: Free-text 'secondary' from a UI; zero-based index sent as 0 (indices are 1-based, 0 is dropped); type-name form used on a single-type (non-combo) chart where no series matches.
Related errors
- Unknown chart preset '{value}'. Available: {string.Join(", "
- Invalid labelPos '{value}' for pie chart: ST_DLblPosPie allo
- Invalid labelPos '{value}': expected one of ctr, inBase, inE
- axisMin={value} is invalid on a log-scaled axis: a logarithm
- Invalid majorUnit '{value}': must be a positive number (OOXM
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/4d4dcd76be4b1ee7.
Report an issue: GitHub.