lobehub/lobehub · error · Error

${path}.series must be a non-empty array

Error message

${path}.series must be a non-empty array

What it means

Thrown by `visualizationSeries` during verify visualization validation when a chart type that requires a `series` array (bar-chart, line-chart) has an `encoding.series` that is either not an array or is an empty array. At least one series is required so the chart has data to plot. `${path}` is `visualizations[i].encoding`.

Source

Thrown at apps/cli/src/commands/verifyHelpers.ts:198

) => {
  if (encoding[key] === undefined) return;
  visualizationField(encoding, key, fieldKeys, path);
};

const optionalVisualizationString = (value: Record<string, unknown>, key: string, path: string) => {
  if (value[key] !== undefined && !firstString(value[key])) {
    throw new Error(`${path}.${key} must be a non-empty string`);
  }
};

const visualizationSeries = (
  encoding: Record<string, unknown>,
  fieldKeys: Set<string>,
  path: string,
  options?: { styles?: boolean },
) => {
  if (!Array.isArray(encoding.series) || encoding.series.length === 0) {
    throw new Error(`${path}.series must be a non-empty array`);
  }
  encoding.series.forEach((rawSeries, seriesIndex) => {
    const series = objectValue(rawSeries);
    const seriesPath = `${path}.series[${seriesIndex}]`;
    if (!series) throw new Error(`${seriesPath} must be an object`);
    visualizationField(series, 'field', fieldKeys, seriesPath);
    if (series.label !== undefined && !firstString(series.label)) {
      throw new Error(`${seriesPath}.label must be a non-empty string`);
    }
    if (
      options?.styles &&
      series.style !== undefined &&
      !['accent', 'muted', 'primary'].includes(String(series.style))
    ) {
      throw new Error(`${seriesPath}.style is invalid`);
    }
  });
};

View on GitHub (pinned to 10f24d7ade)

Solutions

  1. Add at least one series entry: `{field: '<datasetField>', label?: '...'}`.
  2. Ensure each series references a real declared dataset field.
  3. If you intended a chart without series, switch the `type` to one that does not require it (e.g. `scatter-plot`, `metric-comparison`).
  4. For templated manifests, fail fast when the series source list is empty rather than emitting `series: []`.

Example fix

// before
{ "type": "bar-chart", "encoding": { "category": "model", "series": [] } }
// -> visualizations[0].encoding.series must be a non-empty array

// after
{ "type": "bar-chart", "encoding": {
    "category": "model",
    "series": [ { "field": "scores", "label": "Score" } ]
}}
Defensive patterns

Strategy: validation

Validate before calling

function assertSeries(encoding: Record<string, unknown>, path: string) {
  if (!Array.isArray(encoding.series) || encoding.series.length === 0) {
    throw new Error(`${path}.series must be a non-empty array`);
  }
}

Type guard

const hasNonEmptySeries = (v: unknown): v is { series: unknown[] } =>
  !!v && typeof v === 'object' && Array.isArray((v as any).series) && (v as any).series.length > 0;

Prevention

When it happens

Trigger: Omitting `series` entirely for a bar/line chart; setting `series: {}` or `series: "a"`; providing `series: []` with no entries; a templating loop produced zero series because its source list was empty.

Common situations: Building a manifest from a dataset that had no series dimension; a conditional that filtered out all series; copy-pasting a scatter-plot encoding (which has no series) into a bar-chart block.

Related errors


AI-assisted analysis of lobehub/lobehub@10f24d7ade (2026-08-12). Data as JSON: /api/errors/d933dae235140fb7. Report an issue: GitHub.